如无特殊说明,文中的代码均是JDK 1.8版本。
在JDK集合框架中描述过,JDK存储一组Object的集合框架是Collection。而针对Collection框架的一组操作集合体是Collections,里面包含了多种针对Collection的操作,例如:排序、查找、交换、反转、复制等。
这一节讲述Collections的排序操作。
public static > void sort(Listlist) {
list.sort(null);
}
Collections.sort方法调用的是List.sort方法,List.sort方法如下:
@SuppressWarnings({"unchecked", "rawtypes"})default void sort(Comparator super E>c) {
Object[] a= this.toArray();
Arrays.sort(a, (Comparator) c);//Arrays的排序方法
ListIterator i = this.listIterator();for(Object e : a) {
i.next();
i.set((E) e);
}
}
看到这里可能会觉得奇怪,List是接口,但为什么会有实现方法,这是JDK 1.8的新特性。具体特性描述请参考:Java 8接口有default method后是不是可以放弃抽象类了?
在List.sort方法实现中,排序使用的是Arrays#sort(T[], java.util.Comparator super T>)方法,所以Collections的sort操作最终也是使用Arrays#sort(T[], java.util.Comparator super T>)方法。
public static void sort(T[] a, Comparator super T>c) {if (c == null) {
sort(a);
}else{if(LegacyMergeSort.userRequested)
legacyMergeSort(a, c);elseTimSort.sort(a,0, a.length, c, null, 0, 0);
}
}
Arrays#sort(T[], java.util.Comparator super T>)方法使用了3种排序算法:
java.util.Arrays#legacyMergeSort
归并排序,但可能会在新版本中废弃
java.util.ComparableTimSort#sort
不使用自定义比较器的TimSort
java.util.TimSort#sort
使用自定义比较器的TimSort
Arrays源码中有这么一段定义:
/*** Old merge sort implementation can be selected (for
* compatibility with broken comparators) using a system property.
* Cannot be a static boolean in the enclosing class due to
* circular dependencies. To be removed in a future release.*/
static final classLegacyMergeSort {private static final boolean userRequested =java.security.AccessController.doPrivileged(newsun.security.action.GetBooleanAction("java.util.Arrays.useLegacyMergeSort")).booleanValue();
}
该定义描述是否使用LegacyMergeSort,即历史归并排序算法,默认为false,即不使用。所以Arrays.sort只会使用java.util.ComparableTimSort#sort或java.util.TimSort#sort,这两种方法的实现逻辑是一样的,只是java.util.TimSort#sort可以使用自定义的Comparator,而java.util.ComparableTimSort#sort不使用Comparator而已。
顺便补充一下,Comparator是策略模式的一个完美又简洁的示例。总体来说,策略模式允许在程序执行时选择不同的算法。比如在排序时,传入不同的比较器(Comparator),就采用不同的算法。
Timsort算法
Timsort是结合了合并排序(mer