第一次写关于java源码解析的文章,初窥门径,贻笑大方。
整体的架构,java.util.Collections类,它里面实现了对列表排序的功能,提供了一个静态的sort方法,接受一个列表和一个Comparator接口的实例,这个方法的大致实现步骤如下
- 把列表转换为对象数组。
- 通过Array的sort方法来对数组进行排序,出入Comparator接口的实例。
把排好序的数组的数据根据设置回到原来的列表对象中去。
算法的骨架固定,而比较的方法依赖于传入的Comparator接口的实例,内部通过这个接口来回调具体的实现。
下面这段话将Collections的排序委托给了Array
public static <T> void sort(List<T> list, Comparator<? super T> c) {
Object[] a = list.toArray();
Arrays.sort(a, (Comparator)c);
....}
数组中排序的方法如下
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, c);
}
一般会采用TimSort中的sort方法进行排序,依然依赖于传入的Comparator的具体实现
Comparator接口的对象必须实现Compare(Objet obj1,Object obj 2)方法,在该方法中若boj1逻辑上大于obj2,则返回正值,若二者相等则返回0,若obj1逻辑上小于obj2则返回负值.而在TimeSort中,具体的比较策略采用的是mergeSort(归并排序)和binarySort(插入排序)混合的策略。由下面代码可知
// If array is small, do a "mini-TimSort" with no merges if (nRemaining < MIN_MERGE) { int initRunLen = countRunAndMakeAscending(a, lo, hi, c); binarySort(a, lo, hi, lo + initRunLen, c); return; }
// Push run onto pending-run stack, and maybe merge ts.pushRun(lo, runLen); ts.mergeCollapse();
采用递归的方法进行归并排序,当递归的序列长度小于MIN_Merget = 32时,就采用插入排序,从而保证算法的稳定性。