话不多说,直接看代码,从 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 的位置,以此来实现你想要的排序规则。
最后,给两个具体的实现代码(重点看注释部分!):
如果本篇文章有帮助到你的话,可以点个赞呀。