Collections和Arrays的默认排序

参考https://blog.csdn.net/bruce_6/article/details/38299199

总图:

Collections和Arrays的默认排序

Arrays.sort(str);    str为Object[]

Collections.sort(array);   array为List<Type>
JDK 1.6及1.6以前使用,不加比较器是因为其实现了Comparable接口,加入比较器就按照比较器的规则来比较       

/*

public static void sort(Object[] a) {
       if (LegacyMergeSort.userRequested)
                legacyMergeSort(a);
            else
                ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
        }
         */
        /*
        @SuppressWarnings({"unchecked", "rawtypes"})
    private static void mergeSort(Object[] src,Object[] dest,int low,int high,int off) {
        int length = high - low;
        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {       INSERTIONSORT_THRESHOLD=7
            for (int i=low; i<high; i++) 
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

===========================JDK 1.7后

    static void sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen) {
        assert 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) {      32
            int initRunLen = countRunAndMakeAscending(a, lo, hi);
            binarySort(a, lo, hi, lo + initRunLen);
            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.
         */
        ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
        int minRun = minRunLength(nRemaining);
        do {
            // Identify next run
            int runLen = countRunAndMakeAscending(a, lo, hi);

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

 

private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,Comparator<? super T> c) {

        assert lo < hi;

        int runHi = lo + 1;

        if (runHi == hi)

            return 1;

        // Find end of run, and reverse range if descending

        if (c.compare(a[runHi++], a[lo]) < 0) { // Descending

            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)

                runHi++;

            reverseRange(a, lo, runHi);

        } else {                              // Ascending

            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)

                runHi++;

        }

        return runHi - lo;

    }

a) 从数组开始处找到一组连接升序或严格降序(找到后翻转)的数 
b) Binary Sort:使用二分查找的方法将后续的数插入之前的已排序数组,binarySort 对数组 a[lo:hi] 进行排序,并且a[lo:start] 是已经排好序的。算法的思路是对a[start:hi] 中的元素,每次使用binarySearch 为它在a[lo:start] 中找到相应位置,并插入。

================================================================================================

ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);

        int minRun = minRunLength(nRemaining);

        do {

            // Identify next run

            int runLen = countRunAndMakeAscending(a, lo, hi);

 

            // 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);

                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;

===============================================================

    private static int minRunLength(int n) {

        assert n >= 0;

        int r = 0;      // Becomes 1 if any 1 bits are shifted off

        while (n >= MIN_MERGE) {

            r |= (n & 1);

            n >>= 1;

        }

        return n + r;

    }

(2)开始真正的TimSort过程:

      (2.1) 选取minRun大小,之后待排序数组将被分成以minRun大小为区块的一块块子数组

a) 如果数组大小为2的N次幂,则返回16(MIN_MERGE / 2)
b) 其他情况下,逐位向右位移(即除以2),直到找到介于16和32间的一个数  错误:r=0 因为r是在 n >>= 1;前,这时n是偶数,其实n不一定为偶数,可能n=35 所以r可能为1

r |= (n & 1); n >>= 1;