Arrays.sort(Object[] arr)排序源码分析

简介:
    在1.8之前的版本中对此方法进行了重写,如果还需要使用之前的排序算法,需要加上系统属性java.util.Arrays.useLegacyMergeSort=true,之前的排序使用优化后的归并排序,在1.8中使用TimSort算法来进行排序,TimSort算法是由Tim Peters在2002提出并首先实现在了phtyon中,是结合了合并排序(merge sort)和插入排序(insertion sort)的一种高效稳定的算法。算法原理看这里 https://blog.csdn.net/yangzhongblog/article/details/8184707

Arrays.sort(Object[] a)分析
1、 方法声明

/**
 * 根据Comparable的自然排序将给定数组升序排序。所有元素必须实现Comparable 接口
 * 而且,所有元素能相互比较,不然可能会抛出ClassCastException异常
 *
 * 此排序确保是稳定的,如果两个元素e1.equals(e2),那么他们不会被再次排序
 *
 * 该实现是一个稳定、自适应、重复的归并排序,当给定数组是局部排序的数组时它的时间复杂度比 nlogn更小,
 * 然而当给定数组是随机排序,它与传统的归并排序性能相同。如果给定数组大体有序,该算法只需要大概n次比较即可完成排序。
 *
 * 该算法在输入数组为升序或降序时都能发挥优势,并且在该数组部分有序的情况下也能发挥其优势,
 * 它能通过简单连接即可很好的完成将多个数组进行合并
 */
public static void sort(Object[] a) {
//如果要兼容1.8之前的排序程序,在系统属性中需要添加属性,如:java -jar -Djava.Arrays.uselegacyMergeSort=true xx.jar
    if (LegacyMergeSort.userRequested)
        legacyMergeSort(a);
    else
		//真正的TimSort算法实现在ComparableTimSort中
        ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
	}

2、 ComparableTimSort.sort(Object[] a, int lo, int hi, Object[] work, int workBase, int workLen)分析

/**
 * 将数组指定范围内的元素排序
 *
 * [@param](https://my.oschina.net/u/2303379) a 被排序数组
 * [@param](https://my.oschina.net/u/2303379) lo 排序开始元素index
 * [@param](https://my.oschina.net/u/2303379) hi 排序结束元素index,不包含此index
 * [@param](https://my.oschina.net/u/2303379) work a workspace array (slice)
 * [@param](https://my.oschina.net/u/2303379) 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;
	//对于只有0|1个元素的数组,不需要进行排序
    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);
		//使用二叉插入排序对在initRunLen后的元素进行排序
        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对象
    ComparableTimSort ts = new ComparableTimSort(a, work, workBase, workLen);
	//计算最小run的长度
    int minRun = minRunLength(nRemaining);
    do {
        // Identify next run
		//计算当前排序的run的长度,如果为递减数组则翻转
        int runLen = countRunAndMakeAscending(a, lo, hi);

        // If run is short, extend to min(minRun, nRemaining)
		//如果当前run的长度小于minRun,则进行扩展,在扩展过程中使用二叉排序来排序扩展的的元素
        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
		//将此run放入栈中
        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;
	//保证最后的run都被合并
    ts.mergeForceCollapse();
    assert ts.stackSize == 1;
}

转载于:https://my.oschina.net/u/3286119/blog/2055991

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值