使用 Collections.sort() 比較長值
1. 簡介
在本教程中,我們將探討如何使用Collections.sort()
方法對Long
值進行排序。 Java 提供了一個簡單的列表排序方法,但是在處理Long
值時,我們需要了解 Java 如何比較物件。
2. 理解Long
值的自然排序
Collections.sort()
方法預設會以自然順序對元素進行排序。對於像Long
這樣的數字類型,自然順序會依照從小到大的順序排列值。這是無縫工作的,因為Long
類別實現了Comparable
接口,該接口定義了內在的排序行為。
例如,使用compareTo()
方法比較 500L 和 200L 時:
Long a = 500L;
Long b = 200L;
int result = a.compareTo(b);
// result > 0 because 500 > 200
當沒有提供明確的比較器時Collections.sort()
等方法預設使用此自然排序。讓我們來看一個根據自然順序比較Long
值的範例:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, 200L, 800L));
Collections.sort(numbers);
assertEquals(Arrays.asList( 200L , 500L , 800L ), numbers);
當呼叫Collections.sort()
時,Java 內部使用compareTo()
方法來比較元素。 Long
compareTo()
方法的工作原理如下:
- 如果 a < b,則傳回負數
- 如果 a == b,則回傳零
- 如果 a > b,則傳回一個正數。
這種方法非常簡單,非常適合大多數需要升序排列的用例,例如按時間順序排列交易金額或對時間戳進行排序。
3. 使用Comparator
依降序比較Long
值
如果我們想要反轉自然比較順序,我們可以使用Comparator.reverseOrder()
,它會以降序來比較Long
值。這提供了一種直接修改底層比較邏輯的替代方法。
讓我們看看如何以降序比較Long
值:
Collections.sort(numbers, Comparator.reverseOrder());
assertEquals(Arrays.asList( 800L , 500L , 200L ), numbers);
Comparator.reverseOrder()
比較器反轉自然比較,確保Long
值按降序進行比較,而無需手動實現比較器。
4. 使用Comparator
建立自訂比較邏輯
除了簡單的升序或降序比較之外,如果我們需要對排序有更多的控制,我們還可以建立自訂Comparator
。例如,按降序排列值或對某些數字進行優先排序(例如,偶數優先)需要自訂邏輯。
Java 的Comparator
介面允許我們明確地定義這些規則。 Comparator
充當比較兩個元素的藍圖,支援超越自然排序的靈活排序策略。
假設我們要根據Long
值與目標值(例如400L
的距離來比較它們。讓我們針對這個需求創建一個自訂的Comparator
:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, 200L, 800L));
long target = 400L;
Collections.sort(numbers, (a, b) -> {
long distanceA = Math.abs(a - target);
long distanceB = Math.abs(b - target);
return Long.compare(distanceA, distanceB);
});
assertEquals(Arrays.asList( 500L , 200L , 800L ), numbers);
在此範例中,比較邏輯是基於每個Long
值與目標值400L
的距離。比較器計算每個Long
值與目標之間的絕對差,然後比較這些距離。
5. 使用多個條件比較Long
值
在某些情況下,我們可能希望根據多個標準來比較Long
值。例如,我們可能希望按絕對值或其他業務規則對Long
值進行排序。這可以透過使用多個比較條件來實現。
讓我們考慮這樣一個場景,我們需要先按絕對值排序,如果是平局,則按原始值排序。這可以透過連結比較器來實現:
List<Long> numbers = new ArrayList<>(Arrays.asList(-500L, 200L, -800L, 300L));
Collections.sort(numbers, Comparator.comparingLong(n -> Math.abs((Long) n))
.thenComparingLong(n -> (Long) n));
assertEquals(Arrays.asList(200L, 300L, -500L, -800L), numbers);
thenComparing()
方法用於增加二次比較標準。在這種情況下,首先使用Comparator.comparingLong(Math::abs)
以絕對值比較Long
值。如果兩個值的絕對值相同,則使用thenComparingLong(Long::longValue)
比較原始值以打破平局。
當存在多個排序規則時,這種方法特別有用,例如按值排序,然後按時間戳或名稱排序。
6. Long
比較中的空值處理
Collections.sort()
方法預設不允許為空,如果存在任何空值,則會拋出NullPointerException
。為了解決這個問題,我們可以使用自訂比較器來定義在比較過程中如何處理空值。
我們可以使用Comparator.nullsFirst()
來確保將空值放在排序清單的開頭:
List<Long> numbers = new ArrayList<>(Arrays.asList(500L, null, 200L, 800L));
Collections.sort(numbers, Comparator.nullsFirst(Comparator.naturalOrder()));
assertEquals(Arrays.asList(null, 200L, 500L, 800L), numbers);
或者,我們可以使用Comparator.nullsLast()
將空值定位在清單的末端:
Collections.sort(numbers, Comparator.nullsLast(Comparator.naturalOrder()));
assertEquals(Arrays.asList(200L, 500L, 800L, null), numbers);
7. 根據自訂物件屬性比較Long
值
在很多情況下, Long
值是自訂物件的一部分,我們可能需要根據屬性的值對這些物件進行排序。例如,假設我們有一個Transaction
類,其中有一個Long
欄位用於記錄交易金額。我們可以使用比較器根據Long
值對這些物件進行排序。
以下是一個例子:
class Transaction {
private Long amount;
public Transaction(Long amount) {
this.amount = amount;
}
public Long getAmount() {
return amount;
}
}
List<Transaction> transactions = new ArrayList<>();
transactions.add(new Transaction(500L));
transactions.add(new Transaction(200L));
transactions.add(new Transaction(800L));
// Sorting transactions by amount
Collections.sort(transactions, Comparator.comparingLong(Transaction::getAmount));
assertEquals(Arrays.asList(200L, 500L, 800L), transactions.stream().map(Transaction::getAmount).collect(Collectors.toList()));
此程式碼使用Comparator.comparingLong()
方法根據amount
欄位對Transaction
物件清單進行排序。當Long
值包裝在自訂物件中時,這種方法很有用。
8. 結論
在本文中,我們探討了使用Java 的Collections.sort()
方法來比較Long
值的各種方法。我們討論了自然排序、自訂比較器、處理空值以及基於多種標準的比較。這些技術使我們能夠為Long
值定義精確的比較邏輯,
無論是使用簡單列表還是自訂物件。
與往常一樣,原始碼可 在 GitHub 上取得。