| 維度 | Comparable (內部比較器) | Comparator (外部比較器) |
|---|---|---|
| 所在包 | java.lang | java.util |
| 核心方法 | int compareTo(T o) | int compare(T o1, T o2) |
| 實現位置 | 目標類內部 | 獨立類或匿名類 |
| 修改源碼 | 需要 | 不需要 |
| 適用場景 | 自然排序、單一維度 | 多種排序策略、第三方類 |
public class Person implements Comparable<Person> {
private String name;
private int age;
// 構造器、Getter/Setter 省略
@Override
public int compareTo(Person other) {
// 首先按姓名排序
int nameCmp = this.name.compareTo(other.name);
if (nameCmp != 0) return nameCmp;
// 姓名相同則按年齡升序
return Integer.compare(this.age, other.age);
}
}
// 使用:直接排序
List<Person> people = ...;
Collections.sort(people); // 無需傳入比較器
public class Person {
private String name;
private int age;
// 無需實現 Comparable
}
// 策略一:按年齡降序
public class AgeDescComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return Integer.compare(p2.age, p1.age); // 降序
}
}
// 策略二:按姓名長度排序
public class NameLengthComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return Integer.compare(p1.name.length(), p2.name.length());
}
}
// 使用:靈活切換策略
List<Person> people = ...;
Collections.sort(people, new AgeDescComparator());
Collections.sort(people, new NameLengthComparator());
// Java 8+ Lambda 寫法更簡潔
people.sort(Comparator.comparing(Person::getAge).reversed());
people.sort(Comparator.comparing(p -> p.getName().length()));
// 先按部門升序,再按薪資降序
Comparator<Employee> composite = Comparator
.comparing(Employee::getDepartment)
.thenComparing(Employee::getSalary, Comparator.reverseOrder());
employees.sort(composite);
ComparableComparatorComparable 可直接用作鍵;否則構造時必須傳入 ComparatorComparable 實現類最好實現 Serializable,Comparator 同理compare(a,b) 與 compare(b,a) 符號必須相反,且傳遞性必須成立Comparator.nullsFirst()/nullsLast() 顯式聲明Integer.compare() 等靜態方法,避免拆箱開銷與空指針Comparable 定義對象的「自然順序」,屬於類的內在屬性;Comparator 定義「外部排序策略」,屬於操作層面的邏輯。實際開發中常配合使用:類實現 Comparable 作為默認排序,特定業務場景再通過 Comparator 覆蓋或擴展。