Arrays.sort()源码分析

本文详细分析了Java中Arrays.sort()方法对整型数组的排序实现,特别是针对不同长度数组采用的排序策略,包括插入排序、双轴快速排序和归并排序。对于长度小于47的数组,使用插入排序;长度在47到286之间,使用双轴快速排序;长度大于286时,根据无序程度选择排序方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

6版本以下用插入和归并判断的
7版本object的排序依然用的归并排序,int和其他基本类型用的改进的插入排序双轴快速排序和归并排序,但归并排序已经被注释即将过时.
java8以上数组元素个数<47用的插入排序,大于47小于286用的双轴快速插入,大于286后做判断,判断原则是以已经分成若干子区域的数组的无序程度,如果无序程度大于67,依然使用双轴快速排序,小于67使用归并排序.
First, Arrays.sort(int[] a) analysis
Summarize the Arrays.sort(int[] a) method:

  1. Array length 0-47: Strip
  2. Array length 47-286: Dual-Pivot fast row
  3. Array length >286
  4. The array is basically ordered: merge
  5. Array out of order: Dual-Pivot fast row

Arrays.sort has a number of overloaded methods. Here we look at the Arrays.sort(int[] a) method. Other methods are similar.

Public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
You can see that the Sort method of the DualPivotQuicksort class is called. The DualPivotQuicksort is a quick sort. The students who want to know can read these two articles and explain them very thoroughly:

Two-axis fast sorting - implementation principle
Why is DualPivotQuicksort better than regular fast row?

Let’s take a look at the DualPivotQuicksort.sort method:

Static void sort(int[] a, int left, int right,
                 Int[] work, int workBase, int workLen) {

    /**
     * When the array length to be sorted is less than QUICKSORT_THRESHOLD=286:
     * Call sort(a, left, right, true); simply say this method:
     * When the array length is less than INSERTION_SORT_THRESHOLD=47, use the strip,
     * Use the DualPivotQuicksort dual-axis quick release between 47-286.
     */
    If (right - left < QUICKSORT_THRESHOLD) {
        Sort(a, left, right, true);
        Return;
    }
    
    Int[] run = new int[MAX_RUN_COUNT + 1];
    Int count = 0;
    Run[0] = left;

    /**
     * At this point, the array length is >286. If the array is basically ordered, it is to use the two-axis fast row, otherwise use the merge sort
     *
     *
     * The mechanism for judging whether an array has been basically ordered is:
     *
     * Divide the array into several sub-blocks that are incremented or decremented, and store the demarcation points of each block in the run array, for example:
     *
     * Array arr = {9, 6, 6, 4, 8, 20, 18, 17, 16, 15}
     * Can be divided into three blocks
     * {9, 6, 6, 4} {8, 20} {18, 17, 16, 15}
     *
     * The corresponding run array is
     * {0, 4, 6, 10, 0, 0, 0, 0,...},
     * indicates that arr[0]-arr[4-1] is the first block,
     * indicates that arr[4]-arr[6-1] is the second block.
     * indicates that arr[6]-arr[10-1] is the third block.
     *
     * If the block in the array exceeds MAX_RUN_COUNT=67, the array is out of order, and use Dual-Pivot to queue up.
     * Conversely indicates that the order is high, and the merge sort is used at this time.
     */
    For (int k = left; k < right; run[count] = k) {
        // Equal items in the beginning of the sequence
        While (k < right && a[k] == a[k + 1])
            k++;
        /**
         * indicates that the array is already in an ordered state. count=0
         */
        If (k == right) break; // Sequence finishes with equal items

        If (a[k] < a[k + 1]) { // ascending
            /**
             * Find the boundaries of sequential blocks
             */
            While (++k <= right && a[k - 1] <= a[k]) ;
        } else if (a[k] > a[k + 1]) { // descending
            /**
             * Find the boundary of the reverse block
             */
            While (++k <= right && a[k - 1] >= a[k]) ;
            /**
             * Adjust the reverse block to make it a sequential block
             */
            For (int lo = run[count] - 1, hi = k; ++lo < --hi; ) {
                Int t = a[lo];
                a[lo] = a[hi];
                a[hi] = t;
            }
        }

        /**
         * When a reverse block is adjusted to a sequential state, it is compared with the adjacent adjacent block,
         * See if the last element of the last sequential block (which is also the largest one) is smaller than the first element of the current sequential block (which is also the smallest element)
         * If befor.last <= this.first Description These two blocks can be merged together to form a sequential block, at which point count--, eliminates a reverse block
         */
        If (run[count] > left && a[run[count]] >= a[run[count] - 1]) {
            Count--;
        }

        /**
         * When the array is already basically ordered, use the fast row
         */
        If (++count == MAX_RUN_COUNT) {
            Sort(a, left, right, true);
            Return;
        }
    }

    /**
     * count == 0 means the array is already in sequential state
     */
    If (count == 0) {
        Return;
    } else if (count == 1 && run[count] > right) {
        Return;
    }
    Right++;
    If (run[count] < right) {
        Run[++count] = right;
    }

    /**
     * The following is the use of merge sorting
     */
    Byte odd = 0;
    For (int n = 1; (n <<= 1) < count; odd ^= 1) ;

    / / Create a temporary array b used to merge
    Int[] b; // temp array; alternates with a
    Int ao, bo; // array offsets from 'left'
    Int blen = right - left; // space needed for b
    If (work == null || workLen < blen || workBase + blen > work.length) {
        Work = new int[blen];
        workBase = 0;
    }
    If (odd == 0) {
        System.arraycopy(a, left, work, workBase, blen);
        b = a;
        Bo = 0;
        a = work;
        Ao = workBase - left;
    } else {
        b = work;
        Ao = 0;
        Bo = workBase - left;
    }

    // merge, complete condition: reverse order count=1
    For (int last; count > 1; count = last) {
        For (int k = (last = 0) + 2; k <= count; k += 2) {
            Int hi = run[k], mi = run[k - 1];
            For (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
                If (q >= hi || p < mi && a[p + ao] <= a[q + ao]) {
                    b[i + bo] = a[p++ + ao];
                } else {
                    b[i + bo] = a[q++ + ao];
                }
            }
            Run[++last] = hi;
        }
        
        //If the number of subsequences is an odd number, the two will be merged one after the other, and this part will be copied to b.
        If ((count & 1) != 0) {
            For (int i = right, lo = run[count - 1]; --i >= lo;

发送反馈
历史记录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值