話不多說,直接看代碼,從 Collections 的 sort 方法開始。
Collections 類帶有比較器的 sort 方法會進入到 List 接口的一個默認方法:
Collections.sort(dogs, new DogAgeComparator());
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
...
}
再進入到 Arrays 類的 sort 方法:
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
如果有自定義的外部排序(Comparator),就會進入第 4 行的 else 語句塊中,其中的 LegacyMergeSort 排序已經被廢棄(如果你指定使用該方法也可以),現在用的是 TimSort 的排序方法,相比起舊版本直接使用 歸併排序 算法,新版本在此基礎上還引入了 “二分插入排序” 的優化。
接下來,因爲我們討論的主題是 Comparator 和 Comparable 中方法的返回值對排序結果的影響,新版本雖然優化了排序性能,但原本的思想不會有改變,所以我們採用舊版本排序代碼的分析。
LegacyMergeSort 的 mergeSort 算法中的實現了外部比較器 Comparator的代碼:
或者實現了 Comparable 接口的實現:
最爲關鍵的部分,第 4 行使用到的 compare 方法中的 dest[j-1] 和 dest[j],調用結果 > 0 的條件下,會進行 swap,交換他們的位置。
看上面的圖片代碼, o1 代表的是暫時排在前面的元素,o2 代表排在後面的元素。
只要記住,return 值 > 0 的時候會交換 o1 和 o2 的位置,以此來實現你想要的排序規則。
最後,給兩個具體的實現代碼(重點看註釋部分!):
如果本篇文章有幫助到你的話,可以點個贊呀。