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;
}