JAVA 排序用法
目錄
背景和價值
Java 中的比較器(Comparator)是函數(shù)式編程中非常重要的一部分,它主要用于自定義排序規(guī)則。在 Java 8 之后,結(jié)合 Lambda 表達式和 Stream API,它的用法變得更加簡潔和強大。
Java 提供了兩種主要的比較機制:
Comparable接口: 用于對象自身的默認排序(自然排序)。Comparator接口: 用于定義外部的自定義排序規(guī)則。
一、 Comparator 的基本用法
Comparator<T> 是一個函數(shù)式接口,只有一個抽象方法:
public interface Comparator<T> {
int compare(T o1, T o2); // 核心方法
// ... default 和 static 方法
}
- 如果
compare(o1, o2)返回 負數(shù),表示o1排在o2前面。 - 如果
compare(o1, o2)返回 零,表示o1和o2相等。 - 如果
compare(o1, o2)返回 正數(shù),表示o1排在o2后面。
二、 Java 8 之前(匿名內(nèi)部類)
在 Java 8 之前,你需要使用匿名內(nèi)部類來實現(xiàn) Comparator:
List<Student> students = new ArrayList<>();
// ... 填充數(shù)據(jù)
// 按分數(shù)升序排序
Collections.sort(students, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
return s1.getScore() - s2.getScore();
// 或使用包裝類的方法:Integer.compare(s1.getScore(), s2.getScore());
}
});
三、 Java 8 之后(Lambda 表達式和方法引用)
Java 8 極大地簡化了 Comparator 的使用。
1. 使用 Lambda 表達式
由于 Comparator 是一個函數(shù)式接口,可以直接用 Lambda 表達式實現(xiàn) compare 方法:
// 按分數(shù)升序排序
Collections.sort(students, (s1, s2) -> s1.getScore() - s2.getScore());
// 在 Stream 中使用 (分數(shù)降序排序)
students.stream()
.sorted((s1, s2) -> s2.getScore() - s1.getScore()) // s2 減 s1 實現(xiàn)降序
.forEach(System.out::println);
2. 使用靜態(tài)工廠方法 Comparator.comparing()(推薦)
這是最推薦的方式,它允許你使用方法引用來指定排序的鍵(key):
- 按分數(shù)升序:
students.stream() .sorted(Comparator.comparing(Student::getScore)) // 默認升序 .forEach(System.out::println); - 按分數(shù)降序:
students.stream() .sorted(Comparator.comparing(Student::getScore).reversed()) // .reversed() 翻轉(zhuǎn)順序 .forEach(System.out::println); - 按字符串(例如:姓名)升序:
students.stream() .sorted(Comparator.comparing(Student::getName)) .forEach(System.out::println);
3. 鏈式比較(多條件排序)
你可以使用 thenComparing() 來指定第二個、第三個等排序規(guī)則,這在第一個字段相同時非常有用。
示例:先按專業(yè)升序,如果專業(yè)相同,則按分數(shù)降序。
students.stream()
.sorted(
Comparator.comparing(Student::getMajor) // 1. 主要排序:按專業(yè)升序
.thenComparing(Comparator.comparing(Student::getScore).reversed()) // 2. 次要排序:按分數(shù)降序
)
.forEach(System.out::println);
4. 處理 null 值
如果排序字段可能為 null,可以使用 nullsFirst() 或 nullsLast() 來指定 null 值的排序位置。
示例:按姓名排序,null 姓名排在最后。
students.stream()
.sorted(
Comparator.comparing(Student::getName, Comparator.nullsLast(String::compareTo))
)
.forEach(System.out::println);
總結(jié)要點
| 用法 | 描述 | 示例 |
|---|---|---|
| 基礎(chǔ)升序 | 使用 comparing() 傳入 Getter 方法引用。 |
Comparator.comparing(Student::getScore) |
| 基礎(chǔ)降序 | 在基礎(chǔ)升序后調(diào)用 reversed()。 |
Comparator.comparing(Student::getScore).reversed() |
| 多條件排序 | 使用 thenComparing() 鏈接多個比較器。 |
comparing(...).thenComparing(...) |
| 原始類型 | comparingInt(), comparingLong(), comparingDouble() 效率更高。 |
Comparator.comparingInt(Student::getScore) |
| 處理 Null | 使用 nullsFirst() 或 nullsLast() 包裹。 |
Comparator.nullsFirst(Comparator.comparing(Student::getName)) |

浙公網(wǎng)安備 33010602011771號