首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java Comparable 與 Comparator 徹底比較:內部排序 vs 外部策略

     編輯:Java 相關知識

一、核心差異一覽

維度Comparable<T>Comparator<T>
定義位置類內部(實作介面)類外部(獨立類或 Lambda)
核心方法int compareTo(T o)int compare(T o1, T o2)
語義「自然順序」「定製順序」/ 多種排序策略
適用場景單一預設排序、TreeSet/TreeMap 鍵多維度排序、第三方類無法修改
排序呼叫Collections.sort(list)Collections.sort(list, cmp)

二、Comparable 實作範例

public class Person implements Comparable {
    private String name;
    private int age;

    // 自然順序:按姓名字典序
    @Override
    public int compareTo(Person o) {
        return this.name.compareTo(o.name); // null 安全需自行處理
    }
}

// 使用
List list = Arrays.asList(new Person("Bob", 30), new Person("Alice", 25));
Collections.sort(list); // 按 name 排序

三、Comparator 多策略實作

1. 獨立類(Java 7 風格)

class AgeAscComparator implements Comparator {
    @Override public int compare(Person a, Person b) {
        return Integer.compare(a.getAge(), b.getAge());
    }
}
class AgeDescComparator implements Comparator {
    @Override public int compare(Person a, Person b) {
        return Integer.compare(b.getAge(), a.getAge());
    }
}

// 使用
Collections.sort(list, new AgeAscComparator());
Collections.sort(list, new AgeDescComparator());

2. Lambda 表達式(Java 8+ 推薦)

// 年齡升序
list.sort(Comparator.comparingInt(Person::getAge));
// 年齡降序
list.sort(Comparator.comparingInt(Person::getAge).reversed());
// 先按姓名,姓名相同再按年齡
list.sort(Comparator.comparing(Person::getName)
                    .thenComparingInt(Person::getAge));

3. 靜態導入工具方法

import static java.util.Comparator.*;

list.sort(comparing(Person::getName)
          .thenComparing(comparingInt(Person::getAge).reversed()));

四、進階技巧:null 安全與串聯

// null 排在最後
Comparator nullsLast = Comparator.nullsLast(comparing(Person::getName));
// 組合:先按部門,部門相同按薪資降序,薪資相同按姓名
list.sort(comparing(Person::getDept)
          .thenComparing(comparingDouble(Person::getSalary).reversed())
          .thenComparing(Person::getName));

五、TreeSet / TreeMap 的鍵排序

// 自然順序(Person 必須實作 Comparable)
Set treeSet = new TreeSet<>();

// 定製順序(無需 Person 實作 Comparable)
Set treeSet2 = new TreeSet<>(Comparator.comparingInt(Person::getAge));
Map treeMap = new TreeMap<>(Comparator.comparing(Person::getName));

六、效能與避坑指南

  • compareTo/compare 返回 int,禁止用減法(a - b 可能溢位),改用 Integer.compare(a, b) 或 Long.compare。
  • 實作 Comparable 類最好實作 equals 並保持一致:compareTo(x) == 0 ⇔ equals(x)。
  • 大量排序優先用 list.sort(cmp)(原地排序),避免 stream().sorted() 額外開銷。
  • 基本型別比較用 comparingInt/Long/Double 避免自動裝箱。

七、總結

Comparable = 內建自然序(單一、侵入式);
Comparator = 外部策略(多重、非侵入、函數式組合)。
Java 8+ 推薦 Comparator 靜態工廠 + Lambda 鏈式調用,代碼更聲明式、可讀性更強。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved