Java Collections类排序学习

jdk自带排序学习,比如我们写一个排序代码

       List score = new ArrayList();
        score.add(1);
        score.add(12);
        score.add(45);
        score.add(67);
       Collections.sort(score);

来看一下sort的实现

    /**
     * Sorts the specified list into ascending order, according to the
     * {@linkplain Comparable natural ordering} of its elements.
     * All elements in the list must implement the {@link Comparable}
     * interface.  Furthermore, all elements in the list must be
     * mutually comparable (that is, {@code e1.compareTo(e2)}
     * must not throw a {@code ClassCastException} for any elements
     * {@code e1} and {@code e2} in the list).
     *
     * 

This sort is guaranteed to be stable: equal elements will * not be reordered as a result of the sort. * *

The specified list must be modifiable, but need not be resizable. * * @implNote * This implementation defers to the {@link List#sort(Comparator)} * method using the specified list and a {@code null} comparator. * * @param the class of the objects in the list * @param list the list to be sorted. * @throws ClassCastException if the list contains elements that are not * mutually comparable (for example, strings and integers). * @throws UnsupportedOperationException if the specified list's * list-iterator does not support the {@code set} operation. * @throws IllegalArgumentException (optional) if the implementation * detects that the natural ordering of the list elements is * found to violate the {@link Comparable} contract * @see List#sort(Comparator) */ @SuppressWarnings("unchecked") public static > void sort(List list) { list.sort(null); }

继续跟进

    /**
     * Sorts this list according to the order induced by the specified
     * {@link Comparator}.
     *
     * 

All elements in this list must be mutually comparable using the * specified comparator (that is, {@code c.compare(e1, e2)} must not throw * a {@code ClassCastException} for any elements {@code e1} and {@code e2} * in the list). * *

If the specified comparator is {@code null} then all elements in this * list must implement the {@link Comparable} interface and the elements' * {@linkplain Comparable natural ordering} should be used. * *

This list must be modifiable, but need not be resizable. * * @implSpec * The default implementation obtains an array containing all elements in * this list, sorts the array, and iterates over this list resetting each * element from the corresponding position in the array. (This avoids the * n2 log(n) performance that would result from attempting * to sort a linked list in place.) * * @implNote * This implementation is a stable, adaptive, iterative mergesort that * requires far fewer than n lg(n) comparisons when the input array is * partially sorted, while offering the performance of a traditional * mergesort when the input array is randomly ordered. If the input array * is nearly sorted, the implementation requires approximately n * comparisons. Temporary storage requirements vary from a small constant * for nearly sorted input arrays to n/2 object references for randomly * ordered input arrays. * *

The implementation takes equal advantage of ascending and * descending order in its input array, and can take advantage of * ascending and descending order in different parts of the same * input array. It is well-suited to merging two or more sorted arrays: * simply concatenate the arrays and sort the resulting array. * *

The implementation was adapted from Tim Peters's list sort for Python * ( * TimSort). It uses techniques from Peter McIlroy's "Optimistic * Sorting and Information Theoretic Complexity", in Proceedings of the * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, * January 1993. * * @param c the {@code Comparator} used to compare list elements. * A {@code null} value indicates that the elements' * {@linkplain Comparable natural ordering} should be used * @throws ClassCastException if the list contains elements that are not * mutually comparable using the specified comparator * @throws UnsupportedOperationException if the list's list-iterator does * not support the {@code set} operation * @throws IllegalArgumentException * (optional) * if the comparator is found to violate the {@link Comparator} * contract * @since 1.8 */ @SuppressWarnings({"unchecked", "rawtypes"}) default void sort(Comparator c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); } }

    /**
     * Sorts the specified array of objects according to the order induced by
     * the specified comparator.  All elements in the array must be
     * mutually comparable by the specified comparator (that is,
     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
     * for any elements {@code e1} and {@code e2} in the array).
     *
     * 

This sort is guaranteed to be stable: equal elements will * not be reordered as a result of the sort. * *

Implementation note: This implementation is a stable, adaptive, * iterative mergesort that requires far fewer than n lg(n) comparisons * when the input array is partially sorted, while offering the * performance of a traditional mergesort when the input array is * randomly ordered. If the input array is nearly sorted, the * implementation requires approximately n comparisons. Temporary * storage requirements vary from a small constant for nearly sorted * input arrays to n/2 object references for randomly ordered input * arrays. * *

The implementation takes equal advantage of ascending and * descending order in its input array, and can take advantage of * ascending and descending order in different parts of the the same * input array. It is well-suited to merging two or more sorted arrays: * simply concatenate the arrays and sort the resulting array. * *

The implementation was adapted from Tim Peters's list sort for Python * ( * TimSort). It uses techniques from Peter McIlroy's "Optimistic * Sorting and Information Theoretic Complexity", in Proceedings of the * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, * January 1993. * * @param the class of the objects to be sorted * @param a the array to be sorted * @param c the comparator to determine the order of the array. A * {@code null} value indicates that the elements' * {@linkplain Comparable natural ordering} should be used. * @throws ClassCastException if the array contains elements that are * not mutually comparable using the specified comparator * @throws IllegalArgumentException (optional) if the comparator is * found to violate the {@link Comparator} contract */ public static void sort(T[] a, Comparator c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }

如果没有自定义排序就执行默认排序

    /**
     * Sorts the specified array of objects into ascending order, according
     * to the {@linkplain Comparable natural ordering} of its elements.
     * All elements in the array must implement the {@link Comparable}
     * interface.  Furthermore, all elements in the array must be
     * mutually comparable (that is, {@code e1.compareTo(e2)} must
     * not throw a {@code ClassCastException} for any elements {@code e1}
     * and {@code e2} in the array).
     *
     * 

This sort is guaranteed to be stable: equal elements will * not be reordered as a result of the sort. * *

Implementation note: This implementation is a stable, adaptive, * iterative mergesort that requires far fewer than n lg(n) comparisons * when the input array is partially sorted, while offering the * performance of a traditional mergesort when the input array is * randomly ordered. If the input array is nearly sorted, the * implementation requires approximately n comparisons. Temporary * storage requirements vary from a small constant for nearly sorted * input arrays to n/2 object references for randomly ordered input * arrays. * *

The implementation takes equal advantage of ascending and * descending order in its input array, and can take advantage of * ascending and descending order in different parts of the the same * input array. It is well-suited to merging two or more sorted arrays: * simply concatenate the arrays and sort the resulting array. * *

The implementation was adapted from Tim Peters's list sort for Python * ( * TimSort). It uses techniques from Peter McIlroy's "Optimistic * Sorting and Information Theoretic Complexity", in Proceedings of the * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, * January 1993. * * @param a the array to be sorted * @throws ClassCastException if the array contains elements that are not * mutually comparable (for example, strings and integers) * @throws IllegalArgumentException (optional) if the natural * ordering of the array elements is found to violate the * {@link Comparable} contract */ public static void sort(Object[] a) { if (LegacyMergeSort.userRequested) legacyMergeSort(a); else ComparableTimSort.sort(a, 0, a.length, null, 0, 0); } /** To be removed in a future release. */ private static void legacyMergeSort(Object[] a) { Object[] aux = a.clone(); mergeSort(aux, a, 0, a.length, 0); }

legacyMergeSort 归并排序默认关闭的,重点关注 ComparableTimSort.sort

    /**
     * Sorts the given range, using the given workspace array slice
     * for temp storage when possible. This method is designed to be
     * invoked from public methods (in class Arrays) after performing
     * any necessary array bounds checks and expanding parameters into
     * the required forms.
     *
     * @param a the array to be sorted
     * @param lo the index of the first element, inclusive, to be sorted
     * @param hi the index of the last element, exclusive, to be sorted
     * @param work a workspace array (slice)
     * @param workBase origin of usable space in work array
     * @param workLen usable size of work array
     * @since 1.8
     */
    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;
    }

如果小于 private static final int MIN_MERGE = 32;大小就进行折半插入排序,如果大于32进行

TimSort排序

    /**
     * Sorts the given range, using the given workspace array slice
     * for temp storage when possible. This method is designed to be
     * invoked from public methods (in class Arrays) after performing
     * any necessary array bounds checks and expanding parameters into
     * the required forms.
     *
     * @param a the array to be sorted
     * @param lo the index of the first element, inclusive, to be sorted
     * @param hi the index of the last element, exclusive, to be sorted
     * @param work a workspace array (slice)
     * @param workBase origin of usable space in work array
     * @param workLen usable size of work array
     * @since 1.8
     */
    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;
    }

Timsort是一个自适应的、混合的、稳定的排序算法,是由Tim Peter于2002年发明的,最早应用在Python中,现在广泛应用于Python、Java、Android 等语言与平台中,作为基础的排序算法使用。其中Java语言的Collection.sort在JDK1.6使用的是普通的归并排序,归并排序虽然时间复杂度低,但是空间复杂度要求较高,所以从JDK1.7开始就更改为了TimSort算法。

Timsort 的时间复杂度是 O(n log n),与归并排序的时间复杂度相同,那它的优势是啥呢,实际上可以认为TimSort排序算法是归并排序算法的优化版,从它的三个特征就可以看出,第二个特征“混合的”,没错,它不单纯是一种算法,而是融合了归并算法和二分插入排序算法的精髓,因此能够在排序性能上表现优异。

总结:排序->自定义接口实现排序->归并排序->折半插入排序->TImSort

欢迎指正交流

你可能感兴趣的:(学习)