Collections.sort 與 List.sort 是 Java 集合排序的雙引擎。本文系統對比自然排序與定製排序、匿名內部類與 Lambda 表達式、舊 API 與 Stream 流式排序,提供生產環境選型標準。
| API | 適用場景 | 特點 |
|---|---|---|
Collections.sort(list) | 元素實現 Comparable | 靜態工具方法,修改原列表 |
Collections.sort(list, comparator) | 需定製排序邏輯 | 策略模式,靈活複用 |
list.sort(comparator) | Java 8+ 首選 | 默認方法,支援並行排序 parallelSort |
list.stream().sorted(...).collect() | 函數式管道、需保留原列表 | 產生新列表,可鏈式組合 |
public class Person implements Comparable {
private String name;
private Integer order; // 排序鍵
// Getter/Setter 省略
@Override
public int compareTo(Person other) {
// 空值安全:將 null 視為最小
return Comparator.nullsFirst(Comparator.naturalOrder())
.compare(this.order, other.order);
}
}
// 使用
List list = Arrays.asList(p2, p1, p3);
Collections.sort(list); // 或 list.sort(null)
// 輸出: name1(order=1), name2(order=2), name3(order=3)
優點: 語義清晰,無需外部比較器。缺點: 修改實體類,只能有一種自然順序。
Collections.sort(list, new Comparator() {
@Override public int compare(Person p1, Person p2) {
return p1.getOrder().compareTo(p2.getOrder());
}
});
// 升序
list.sort(Comparator.comparing(Person::getOrder));
// 降序
list.sort(Comparator.comparing(Person::getOrder).reversed());
// 多鍵排序:先按 order 升序,再按 name 降序
list.sort(Comparator
.comparing(Person::getOrder)
.thenComparing(Person::getName, Comparator.reverseOrder()));
// 空值安全:null 排最後
list.sort(Comparator.comparing(Person::getOrder,
Comparator.nullsLast(Comparator.naturalOrder())));
List sorted = list.stream()
.filter(p -> p.getOrder() != null)
.sorted(Comparator.comparing(Person::getOrder))
.collect(Collectors.toList());
// 並行排序(大數據量)
List parallelSorted = list.parallelStream()
.sorted(Comparator.comparing(Person::getOrder))
.collect(Collectors.toList());
// 靜態導入簡化代碼
import static java.util.Comparator.*;
// 反轉
Comparator desc = comparing(Person::getOrder).reversed();
// 空值處理
Comparator nullsFirst = nullsFirst(naturalOrder());
Comparator nullsLast = nullsLast(comparing(Person::getOrder));
// 比較器鏈
Comparator complex = comparing(Person::getOrder)
.thenComparing(Person::getName, String::compareToIgnoreCase)
.thenComparing(Person::getAge, nullsLast(naturalOrder()));
// 基於鍵提取器的比較器(避免重複獲取屬性)
Comparator byOrder = comparingInt(Person::getOrder); // 基本類型專用,無裝箱
| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 實體類穩定、單一業務排序 | Comparable | 語義內聚,零額外代碼 |
| 多種排序需求、不修改實體 | Comparator.comparing | 策略模式,靈活組合 |
| 需保留原列表、函數式管道 | Stream.sorted | 不可變,易測試 |
| 超大列表(>10萬)、多核 CPU | parallelStream().sorted() | 利用 ForkJoinPool 並行 |
| 基本類型排序鍵 | comparingInt/Long/Double | 避免裝箱開銷 |
compareTo 中直接相減 return a - b → 整數溢出風險Integer.compare(a, b) 或 Comparator.naturalOrder()Comparator.comparing(p -> p.getOrder()) → 無方法引用優化Comparator.comparing(Person::getOrder) → 編譯器優化為 Comparators$ComparableComparatorNPEnullsFirst/Last 明確語義Java 8+ 時代,
Comparator.comparing+ 方法引用 + 鏈式組合是排序代碼的標準範式:類型安全、可讀性強、零裝箱、易並行。拋棄匿名內部類,擁抱函數式比較器。