Collections.sort 这个方法使用了很多次了,剖析他的源码的意义很重要
1.实体类 (为了节省篇幅,大幅度削减)
public class Product {
private int productId;
}
2.排序使用 (下方为正序排序,逆序只需要return o2.getProductId() - o1.getProductId();)
Collections.sort(productList, new Comparator<Product>() {
@Override
public int compare(Product o1, Product o2) {
return o1.getProductId() - o2.getProductId();
}
});
3.sort方法源码
//第一步 调用list的sort方法
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
//第二步 调用Arrays.sort 数组的排序方法
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
//第三步 传入比较器Comparator 调用TimSort.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);
}
}
4.TimSort.sort (排序所使用的算法)
TimSort 是一个归并排序做了大量优化的版本。对归并排序排在已经反向排好序的输入时做了特别优化。对已经正向排好序的输入减少回溯。对两种情况混合(一会升序,一会降序)的输入处理比较好。(来自百度百科)
查看源码发现,Timsort是结合了合并排序(merge sort)和插入排序(insertion sort)而得出的排序算法,它在使用中有很好的效率。
static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) {
assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo;
if (nRemaining < 2)
return; // Arrays of size 0 and 1 are always sorted
// 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;
}
/**
* March over the array once, left to right, finding natural runs,
* extending short natural runs to minRun elements, and merging runs
* to maintain stack invariant.
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
int minRun = minRunLength(nRemaining);
do {
// Identify next run
int runLen = countRunAndMakeAscending(a, lo, hi, c);
// If run is short, extend to min(minRun, nRemaining)
if (runLen < minRun) {
int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}
// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// Merge all remaining runs to complete sort
assert lo == hi;
ts.mergeForceCollapse();
assert ts.stackSize == 1;
}