06-Arrays.sort 和 Collections.sort 实现原理和区别

1.概念

java.util.Collections 是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全等操作。 然后还有混排(Shuffling)、反转(Reverse)、替换所有的元素(fill)、拷贝(copy)、返回Collections中最小元素(min)、返回Collections中最大元素(max)、返回指定源列表中最后一次出现指定目标列表的起始位置( lastIndexOfSubList )、返回指定源列表中第一次出现指定目标列表的起始位(IndexOfSubList )、根据指定的距离循环移动指定列表中的元素(Rotate);

事实上Collections.sort方法底层就是调用的Arrays.sort方法

//Collections.sort方法
    public static <T extends Comparable<? super T>> void sort(List<T> var0) {
        var0.sort((Comparator)null);
    }
//var0.sort
    public void sort(Comparator<? super E> var1) {
        int var2 = this.modCount;
        //Collections.sort方法底层调用的就是Arrays.sort方法
        Arrays.sort((Object[])this.elementData, 0, this.size, var1);
        if (this.modCount != var2) {
            throw new ConcurrentModificationException();
        } else {
            ++this.modCount;
        }
    }

再来看看Arrays.sort方法

    public static <T> void sort(T[] var0, int var1, int var2, Comparator<? super T> var3) {
        if (var3 == null) {//没有设置比较规则走这里
            sort(var0, var1, var2);//sort的实现请看下面的代码块
        } else {//设置了比较规则走这里
            rangeCheck(var0.length, var1, var2);
            //legacyMergeSort归并排序, 默认是不使用这个方法
            if (Arrays.LegacyMergeSort.userRequested) {
                legacyMergeSort(var0, var1, var2, var3);
            } else {//所以使用的是TimSort.sort
            	//TimSort是mergeSort的一种改进
                TimSort.sort(var0, var1, var2, var3, (Object[])null, 0, 0);
            }
        }

    }

sort

    public static void sort(Object[] var0, int var1, int var2) {
        rangeCheck(var0.length, var1, var2);
        if (Arrays.LegacyMergeSort.userRequested) {
            legacyMergeSort(var0, var1, var2);
        } else {
            ComparableTimSort.sort(var0, var1, var2, (Object[])null, 0, 0);
        }

    }

2.函数解释

1.TimSort.sort与ComparableTimSort.sort基本相同, 唯一区别的是后者需要对象是Comparable可比较的,不需要特定Comparator,而前者利用提供的Comparator进行排序

2.TimSort是mergeSort的一种改进, Timsort 排序是结合了归并排序(merge sort)和插入排序(insertion sort)而得出的排序算法

步骤如下:

0、数组长度小于某个值,直接用二分插入排序算法, 否则执行下面的步骤
1、根据数组长度计算minrun(最小run(分区)长度)

2、将数组按升序或者严格降序(需反转为升序)分割成一个一个run(分区),长度小于minrun的分区则使用插入排序进行扩充

3、将分区的首元素下标及长度放入栈中,当栈顶run的长度满足 runLen[n-2] + runLen[n-1] >= runLen[n-3] 
或者满足runLen[n-1] >= runLen[n-2]时(n表示栈中run的个数,下标n-1就是栈顶),使用归并排序将栈顶相邻
最短的两个run进行合并,继续对剩余的数组元素进行分区。

4、数组分区完成后将栈中剩余的run全部合并。
//TimSort.sort(var0, var1, var2, var3, (Object[])null, 0, 0);
 static void sort(Object[] var0, int var1, int var2, Object[] var3, int var4, int var5) {
        assert var0 != null && var1 >= 0 && var1 <= var2 && var2 <= var0.length;

        int var6 = var2 - var1;
        if (var6 >= 2) {
            if (var6 < 32) {//数组元素数量<32用二分插入排序
                int var11 = countRunAndMakeAscending(var0, var1, var2);
                binarySort(var0, var1, var2, var1 + var11);
            } else {
                ComparableTimSort var7 = new ComparableTimSort(var0, var3, var4, var5);
                int var8 = minRunLength(var6);

                do {
                    int var9 = countRunAndMakeAscending(var0, var1, var2);
                    if (var9 < var8) {//长度小于minrun的分区则使用插入排序进行扩充
                        int var10 = var6 <= var8 ? var6 : var8;
                        binarySort(var0, var1, var1 + var10, var1 + var9);
                        var9 = var10;
                    }

                    var7.pushRun(var1, var9);
                    var7.mergeCollapse();
                    var1 += var9;
                    var6 -= var9;
                } while(var6 != 0);

                assert var1 == var2;

                var7.mergeForceCollapse();

                assert var7.stackSize == 1;

            }
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值