1. Arrays.sort基础回顾與Comparator入門當我們第一次接觸Java數組排序時Arrays.sort()往往是首選工具。默認情況下這個方法會按照自然順序從小到大對數組進行排序。比如對整數數組排序時數字會按照0,1,2...的順序排列。但這種基礎排序方式在實際開發中往往不夠用特別是當我們需要處理複雜對象或多維度數據時。Comparator接口的出現解決了這個痛點。它就像一個排序規則生成器允許我們自定義比較邏輯。我記得第一次使用Comparator時發現它其實就是一個只有單一方法compare(T o1, T o2)的函數式接口。這個方法返回的整數值決定了兩個元素的相對順序負數表示o1應該排在o2前面正數表示o2應該排在o1前面零表示兩者相等Integer[] numbers {3, 1, 4, 1, 5, 9}; Arrays.sort(numbers, (a, b) - b - a); // 降序排列這裡的lambda表達式(a, b) - b - a就是一個最簡單的Comparator實現。這種寫法比傳統的匿名類簡潔很多是Java 8帶來的語法糖。2. 多維度排序實戰技巧2.1 二維數組排序處理二維數組時Comparator的威力開始真正顯現。假設我們有一個表示學生成績的二維數組每行包含學號和分數兩個元素。如果我們想先按分數降序分數相同時再按學號升序排列可以這樣實現int[][] students { {1001, 85}, {1002, 90}, {1003, 85}, {1004, 92} }; Arrays.sort(students, (a, b) - { if (a[1] ! b[1]) { return b[1] - a[1]; // 分數降序 } else { return a[0] - b[0]; // 學號升序 } });這種多條件排序在處理報表數據時特別有用。我在一個電商項目中就曾用類似方法對商品按銷量和價格進行組合排序。2.2 對象數組的多字段排序對於自定義對象我們可以通過方法引用進一步簡化代碼。假設有一個Employee類class Employee { String name; int age; double salary; // 構造方法和getter省略 }如果要先按年齡升序再按薪資降序排列Employee[] employees {...}; Arrays.sort(employees, Comparator.comparingInt(Employee::getAge) .thenComparing(Employee::getSalary, Comparator.reverseOrder()) );這裡使用了Comparator的鏈式調用代碼既簡潔又易讀。特別注意thenComparing()方法的使用它讓多條件排序變得非常優雅。3. 業務場景下的自定義排序3.1 特殊排序規則實現實際業務中經常會遇到非常規排序需求。比如對字符串進行智能排序純數字字符串按數值大小混合字符串按字母表順序空字符串排在最後String[] items {100, 42, apple, , banana42}; Arrays.sort(items, (s1, s2) - { if (s1.isEmpty()) return 1; if (s2.isEmpty()) return -1; if (s1.matches(\\d) s2.matches(\\d)) { return Integer.compare(Integer.parseInt(s1), Integer.parseInt(s2)); } return s1.compareTo(s2); });3.2 中文排序處理處理中文排序時可能需要使用Collator類來實現符合本地語境的排序String[] names {張三, 李四, 王五}; Arrays.sort(names, Collator.getInstance(Locale.CHINA));4. 性能優化與最佳實踐4.1 避免自動裝箱開銷對於大型基本類型數組使用自定義Comparator時要注意裝箱開銷。比如對int[]進行降序排序直接操作原始數組比轉換為Integer[]效率更高int[] largeArray {...}; int[] sorted Arrays.stream(largeArray) .boxed() .sorted(Comparator.reverseOrder()) .mapToInt(i - i) .toArray();4.2 緩存Comparator實例如果某個Comparator會被頻繁使用可以將其緩存為靜態實例class EmployeeComparators { static final ComparatorEmployee BY_AGE_THEN_SALARY Comparator.comparingInt(Employee::getAge) .thenComparingDouble(Employee::getSalary); }4.3 並行排序優化對於超大數組可以考慮使用parallelSortEmployee[] bigArray {...}; Arrays.parallelSort(bigArray, EmployeeComparators.BY_AGE_THEN_SALARY);5. 常見陷阱與調試技巧5.1 比較邏輯的一致性問題Comparator必須滿足以下數學性質否則可能導致不可預測的行為自反性compare(a,a) 0對稱性compare(a,b)與compare(b,a)符號相反傳遞性如果compare(a,b)0且compare(b,c)0則compare(a,c)05.2 空值處理策略默認情況下Comparator遇到null會拋出NullPointerException。我們可以使用nullsFirst或nullsLast來處理Arrays.sort(employees, Comparator.nullsLast( Comparator.comparing(Employee::getName) ) );5.3 調試比較邏輯當複雜Comparator出現問題時可以添加日誌輸出Arrays.sort(employees, (a, b) - { int result Integer.compare(a.getAge(), b.getAge()); System.out.printf(Comparing %s and %s: %d%n, a, b, result); return result; });6. Java 8新特性應用6.1 方法引用與Lambda表達式Java 8的方法引用讓Comparator代碼更加簡潔Arrays.sort(employees, Comparator.comparing(Employee::getDepartment) .thenComparing(Employee::getSalary));6.2 反向比較的幾種寫法實現降序排序有多種方式各有優劣Collections.reverseOrder()Comparator.comparing(...).reversed()(a,b) - b.compareTo(a)// 三種等價的降序排序 Arrays.sort(words, Collections.reverseOrder()); Arrays.sort(words, Comparator.comparing(String::toString).reversed()); Arrays.sort(words, (a,b) - b.compareTo(a));6.3 使用Comparator.comparingInt等特化方法對於基本類型字段使用特化方法可以避免裝箱開銷Arrays.sort(employees, Comparator.comparingInt(Employee::getAge) .thenComparingDouble(Employee::getSalary) );7. 複雜業務排序案例7.1 分組優先排序假設需要將員工按部門分組每組內按職級排序且管理部要排在最前面MapString, Integer deptPriority Map.of( 管理部, 1, 技術部, 2, 市場部, 3 ); Arrays.sort(employees, Comparator.comparing((Employee e) - deptPriority.get(e.getDepartment())) .thenComparingInt(Employee::getLevel) );7.2 帶權重的綜合排序在電商商品排序中我們可能需要綜合考慮多個因素Arrays.sort(products, (p1, p2) - { double score1 p1.getSales() * 0.6 p1.getRating() * 0.4; double score2 p2.getSales() * 0.6 p2.getRating() * 0.4; return Double.compare(score2, score1); // 降序 });8. 測試與驗證策略8.1 單元測試模式為排序邏輯編寫測試時可以使用參數化測試Test void testEmployeeSort() { Employee[] testData {...}; Employee[] expected {...}; Arrays.sort(testData, EmployeeComparators.BY_AGE_THEN_SALARY); assertArrayEquals(expected, testData); }8.2 邊界條件驗證特別要測試以下邊界情況空數組單元素數組包含null的數組所有元素相同的數組已經有序或逆序的數組8.3 性能測試方法對於大型數組排序需要監控執行時間和內存使用long start System.nanoTime(); Arrays.sort(largeArray, complexComparator); long duration System.nanoTime() - start; System.out.printf(排序耗時: %.2f ms%n, duration / 1e6);