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

Java 排序深度解析:Comparable、Comparator、中文排序與 TreeSet 源碼全景圖

     編輯:Java 綜合教學

排序核心機制:兩大介面雙驅動

Java 排序體系圍繞兩個核心介面:

  • Comparable<T>:內部排序,類實現 compareTo(T o) 定義「自然順序」。適用於單一、固定排序規則(如 ID 排序)。
  • Comparator<T>:外部排序,獨立類實現 compare(T o1, T o2) 定義「定制順序」。適用於多種排序策略、無法修改原類、或需組合排序。

三大排序入口與底層實現

實戰一:中文拼音排序(Comparator 策略)

// 核心:Collator.getInstance(Locale.CHINA) 實現漢字拼音比較
public class ChineseComparator implements Comparator<String> {
    private final Collator collator = Collator.getInstance(Locale.CHINA);
    @Override public int compare(String o1, String o2) {
        return collator.compare(o1, o2);
    }
}

// 使用
List<String> names = Arrays.asList("張三", "李四", "王五");
Collections.sort(names, new ChineseComparator());
// 結果:李四、王五、張三(按拼音 l, w, z)

實戰二:多字段組合排序(Comparator 鏈式)

// 先按部門升序,再按薪資降序
Comparator<Employee> combo = Comparator
    .comparing(Employee::getDept)
    .thenComparing(Employee::getSalary, Comparator.reverseOrder());

Collections.sort(list, combo);

實戰三:對象實現 Comparable(自然順序)

public class User implements Comparable<User> {
    private String name;
    // getter/setter...
    @Override
    public int compareTo(User o) {
        return Collator.getInstance(Locale.CHINA).compare(this.name, o.name);
    }
}

// 直接排序,無需傳 Comparator
Collections.sort(userList);
TreeSet<User> set = new TreeSet<>(); // 自動按 name 排序

源碼深度剖析:Arrays.sort → TimSort

關鍵流程

  1. Collections.sort(list) → 轉陣列 → Arrays.sort(array) → mergeSort()
  2. TimSort 核心:
    • 小區間(< 7)用二分插入排序。
    • 大區間遞歸分治歸併排序。
    • 合併前檢查 src[mid-1] <= src[mid],已有序則直接 arraycopy 跳過合併。
  3. Comparable 路徑:強轉 (Comparable) obj 調用 compareTo,未實現拋 ClassCastException。
  4. Comparator 路徑:調用傳入 c.compare(o1, o2),無強轉風險。

TreeSet/TreeMap 源碼揭秘

// TreeSet 構造器
public TreeSet(Comparator<? super E> comparator) {
    this(new TreeMap<>(comparator)); // 內部封裝 TreeMap
}

// TreeMap.put 核心邏輯
Comparator<? super K> cpr = comparator;
if (cpr != null) {
    // 使用 Comparator 比較,決定左/右子樹
    cmp = cpr.compare(key, t.key);
} else {
    // 使用 Comparable 比較
    @SuppressWarnings("unchecked")
    Comparable<? super K> k = (Comparable<? super K>) key;
    cmp = k.compareTo(t.key);
}
// 紅黑樹插入平衡:fixAfterInsertion(e)

避坑指南與最佳實踐

  • 空指針安全:Comparator 鏈式寫法自動處理 null;手寫 compare 時先判 null。
  • 一致性原則:compareTo 與 equals 應保持一致(x.compareTo(y)==0 ⟺ x.equals(y)),否則 TreeSet/TreeMap 行為異常。
  • 序列化注意:實現 Comparable 的類建議實現 Serializable,避免分布式傳輸問題。
  • 性能選擇:單一固定順序用 Comparable;多策略、第三方類、組合排序用 Comparator。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
入口方法適用對象底層演算法備註
Collections.sort(List)ListTimSort(歸併+插入混合)元素必須實現 Comparable
Collections.sort(List, Comparator)ListTimSort傳入外部比較器
Arrays.sort(Object[])陣列TimSort運行時檢查 Comparable
TreeSet/TreeMap有序集合紅黑樹插入即排序,構造器可傳 Comparator