java中Arrays.sort()實現原理

先在網上找到一些說法:java

        java中Arrays.sort使用了兩種排序方法,快速排序和優化的合併排序。算法

        快速排序主要是對哪些基本類型數據(int,short,long等)排序, 而合併排序用於對對象類型進行排序。
        使用不一樣類型的排序算法主要是因爲快速排序是不穩定的,而合併排序是穩定的。這裏的穩定是指比較相等的數據在排序以後仍然按照排序以前的先後順序排列。對於基本數據類型,穩定性沒有意義,而對於對象類型,穩定性是比較重要的,由於對象相等的判斷可能只是判斷關鍵屬性,最好保持相等對象的非關鍵屬性的順序與排序前一直;另一個緣由是因爲合併排序相對而言比較次數比快速排序少,移動(對象引用的移動)次數比快速排序多,而對於對象來講,比較通常比移動耗時。
設計模式

        補充一點合併排序的時間複雜度是n*logn, 快速排序的平均時間複雜度也是n*logn,可是合併排序的須要額外的n個引用的空間 ......ide


自定義比較接口:優化

sort(T[] a, Comparator<? super T> c)ui

class Dog{  
    int size;  
    int weight;  
   
    public Dog(int s, int w){  
        size = s;  
        weight = w;   
    }  
}  
   
class DogSizeComparator implements Comparator<Dog>{  
   
    @Override  
    public int compare(Dog o1, Dog o2) {  
        return o1.size - o2.size;  
    }  
}  
   
class DogWeightComparator implements Comparator<Dog>{  
   
    @Override  
    public int compare(Dog o1, Dog o2) {  
        return o1.weight - o2.weight;  
    }  
}  
   
public class ArraySort {  
   
    public static void main(String[] args) {  
        Dog d1 = new Dog(2, 50);  
        Dog d2 = new Dog(1, 30);  
        Dog d3 = new Dog(3, 40);  
   
        Dog[] dogArray = {d1, d2, d3};  
        printDogs(dogArray);  
   
        Arrays.sort(dogArray, new DogSizeComparator());   
        printDogs(dogArray);  
   
        Arrays.sort(dogArray, new DogWeightComparator());     
        printDogs(dogArray);  
    }  
   
    public static void printDogs(Dog[] dogs){  
        for(Dog d: dogs)  
            System.out.print("size="+d.size + " weight=" + d.weight + " ");  
   
        System.out.println();  
    }  
}

爲什麼使用"super"
        若是使用 "Comparator < T > c" 那是很簡單易懂的,可是sort的第2個參數裏面的 < ? super T > 意味着比較器所接受的類型能夠是T或者它的超類. 爲何是超類呢? A:這容許使用同一個比較器對不一樣的子類對象進行比較。spa

基本類型源碼:
設計

/**
     * Sorts the specified array into ascending numerical order.
     *
     * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
     * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
     * offers O(n log(n)) performance on many data sets that cause other
     * quicksorts to degrade to quadratic performance, and is typically
     * faster than traditional (one-pivot) Quicksort implementations.
     *
     * @param a the array to be sorted
     */
    public static void sort(int[] a) {
        DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
    }

從名字可見的確是快排。code

對象類型源碼:orm

 public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

ComparableTimSort.sort:

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

這裏發現若是元素少於MIN_MERGE=32採用binarySort(二分排序);後面還有些判斷bulabula,最後採用mergeForceCollapse(歸併排序)。

真實狀況還要看JDK版本,這裏我用的是JDK8

4. 小結
與Arrays.sort()相關的信息總結以下:

  1. 通用: super 類

  2. 策略設計模式(strategy pattern);

  3. 歸併排序(merge sort): 時間複雜度 n*log(n);

  4. Java.util.Collections#sort(List < T > list, Comparator < ? super T > c)與Arrays.sort 使用相似的思想.

相關文章
相關標籤/搜索