JDK8自帶的兩種排序Arrays.sort()和Collections.sort()

JDK8自帶的兩種排序 Arrays.sort和Collections.sort


Arrays.cort()是數組的排序方法,Collections.sort()是集合的排序方法,兩個方法我們在平時都經常用到,給我們帶來了便利。



一、Arrays.cort()

Arrays.sort(數組名);
Arrays.sort(數組名 ,int fromIndex, int toIndex);

這兩個方法在排序中用到的頻率最高,默認是升序排序,當我們需要默認排序時,就需要花點功夫了。


Arrays.cort()自定義排序
通過自定義一個類實現Comparator接口的compare()方法,再作爲比較器傳參,就可以現在自定義排序了。

public class test1 {
    public static void main(String args[]) throws IOException {
        //注意,要想改變默認的排列順序,不能使用基本類型(int,double, char),而要使用它們對應的類
        Integer[] arr = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
        //定義一個自定義類MyComparator的對象
        Comparator cmp = new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return (Integer)o1 > (Integer)o2 ? -1 :1;
            }
        };
        Arrays.sort(arr,cmp);
        System.out.println(Arrays.toString(arr));
    }
}

Arrays.cort()逆序排序

Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5}; 
Arrays.sort(a,Collections.reverseOrder()); //Collections.reverseOrder()在方法調用返回一個比較器,它強行上實現Comparable接口的對象的集合的自然順序相反。
System.out.println(Arrays.toString(a));


二、Collections.cort()

List<Integer> intList = Arrays.asList(33, 24, 18, 6, 9, 99);
Collections.sort(intList);

Collections.sort()自定義排序

Collections.sort(personList, new Comparator<Person>() {

            @Override
            public int compare(Person p1, Person p2) {
                return p1.getAge() > p2.getAge() ? 1 : -1;//升序
            }

 });


三、面試重點:源碼分析

一、Arrays.sort()

基本類型:採用調優的快速排序;
對象類型:採用改進的歸併排序。

1、基本類型
數組長度小於47的時候是用直接插入算法,大於47並且小於286是採用雙軸快速排序,大於286如果連續性好「也就是元素大多有序,有一個flag專門用來記錄數組元素的升降次數,代表這個數組的連續性」採用的是歸併排序,否則還是依舊採用雙軸快速排序。
小於286(小於47/大於47並且小於286)

private static void sort(int[] a, int left, int right, boolean leftmost) {
        int length = right - left + 1;

        // 長度小於47,使用直接插入排序
        if (length < INSERTION_SORT_THRESHOLD) {
            if (leftmost) {
                /*
                 * Traditional (without sentinel) insertion sort,
                 * optimized for server VM, is used in case of
                 * the leftmost part.
                 */
                for (int i = left, j = i; i < right; j = ++i) {
                    int ai = a[i + 1];
                    while (ai < a[j]) {
                        a[j + 1] = a[j];
                        if (j-- == left) {
                            break;
                        }
                    }
                    a[j + 1] = ai;
                }
            }
            //長度大於47小於286
            else {
                //雙軸快速排序
            }

大於等於286

static void sort(int[] a, int left, int right,
                     int[] work, int workBase, int workLen) {
        // 小於286排序
        if (right - left < QUICKSORT_THRESHOLD) {
            sort(a, left, right, true);
            return;
        }

        /*
         * Index run[i] is the start of i-th run
         * (ascending or descending sequence).
         */
        int[] run = new int[MAX_RUN_COUNT + 1];
        int count = 0; run[0] = left;

        //檢查數組是否接近排好序
        for (int k = left; k < right; run[count] = k) {
            if (a[k] < a[k + 1]) { // 上升
                while (++k <= right && a[k - 1] <= a[k]);
            } else if (a[k] > a[k + 1]) { // 下降
                while (++k <= right && a[k - 1] >= a[k]);
                for (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                    int t = a[lo]; a[lo] = a[hi]; a[hi] = t;
                }
            } else { // 相等
                for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {
                    if (--m == 0) {
                        sort(a, left, right, true);
                        return;
                    }
                }
            }

            /*
             *連續性不好,
             *依然使用快速排序.
             */
            if (++count == MAX_RUN_COUNT) {
                sort(a, left, right, true);
                return;
            }
        }

        //檢查特殊情況
        // Implementation note: variable "right" is increased by 1.
        if (run[count] == right++) { // The last run contains one element
            run[++count] = right;
        } else if (count == 1) { // The array is already sorted
            return;
        }

    		 /*
             *連續性好,
             *使用歸併排序.
             */
    		.............
        }
    }
    

2、對象類型

TimSort.sort()

 public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)//如果設置了歸併排序爲true
            legacyMergeSort(a);
        else//否則使用TimeSort(結合了歸併排序和插入排序)
            ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
    }

當待排序元素小於32個時,採用二分插入排序,是插入排序的一種改進。
當待排序元素大於等於32個時,進行歸併排序。

二、Collectiom.sort()

 @SuppressWarnings({"unchecked", "rawtypes"})
    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);
        }
    }

使用的是Arrays.sort()中的TimSort.sort()


總結:Arrays.sort()分爲基本數據類型和對象類型。Collections.sort()是先轉換爲數組,再調用Arrays.sort(),也就是對象類型。


哪裏寫得不好或者想討論的小夥伴歡迎留言哦!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章