Arrays.sort(Object[] a)源码分析

ε祈祈猫儿з 提交于 2019-12-26 02:07:46

前言

Arrays.sort(Object[] a)是Arrays的一个非常重要的一个静态方法,可以对数组的进行排序,前提是数组中的元素必须实现了Comparable接口。所用的排序方法为归并排序法;作为集合排序的核心,非常重要。

归并排序

归并排序的一个主要的优点:稳定,即不需要交换相同的元素

举例:假设有一个已经按照姓名排列的员工列表。现在,按照工资再按照工资排序。如果两个员工的工资相等会发生什么样的情况呢?如果采用稳定的排序算法,将会保留按名字排序的顺序。换句话说,排序的结果将会产生这样一个列表,首先对按照工资排序,工资相同者再按照名字排序

源码分析

源码一(sort(Object[] a))
static final class LegacyMergeSort {
        private static final boolean userRequested =
            java.security.AccessController.doPrivileged(
                new sun.security.action.GetBooleanAction(
                    "java.util.Arrays.useLegacyMergeSort")).booleanValue();
    }
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);
    }
分析:

从以上代码看出sort方法有两个分支

  • legacyMergeSort(a)
  • ComparableTimSort.sort(a, 0, a.length, null, 0, 0)

首先看第一个代码片段,当System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");时,LegacyMergeSort.userRequested的结果为true,反之为false。这个属性作为分支的依据,当属性值为true时,将会采用legacyMergeSort(a)方法对数组进行排序,反之采用ComparableTimSort.sort(a, 0, a.length, null, 0, 0),由注释/** To be removed in a future release. */可以看到第一个排序算法在将来的版本会被抛弃。

源码二( legacyMergeSort(a))
 private static final int INSERTIONSORT_THRESHOLD = 7;

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

    /**
     * Swaps x[a] with x[b].
     */
    private static void swap(Object[] x, int a, int b) {
        Object t = x[a];
        x[a] = x[b];
        x[b] = t;
    }

分析

主要看算法的核心部分

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

可以看到只有当comparaTo方法返回1才能对数组相邻两个元素调换位置

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!