实战小知识之浅谈Arrays.sort

798 阅读2分钟

这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战

大家日常用到排序的场景都是相对比较多的,无论是刷算法题还是日常业务处理;在编写业务接口的时候,可能会更偏向于把接口逻辑挤压在SQL里面,在SQL完成业务的处理 + 排序。

排序

在刷题的时候,用的最多的就是Array.sort()排序方法。然而排序的实现是基于比较器;默认的就是从小到大的排序;如果需要修改排序的方式,例如倒序的话可以使用匿名内部类重写comparator接口,并实现compare方法。

public static void main(String[] args) {
    Integer[] q = new Integer[]{0,4,1,-1,2};
    Arrays.sort(q);
    System.out.println("从小到大排序");
    for (Integer a :
            q) {
        System.out.print(a+ " ");
    }
    System.out.println("倒序后:");
    Arrays.sort(q,new Comparator<Integer>(){
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2.compareTo(o1);
        }
    });
    for (Integer a :
            q) {
        System.out.print(a+" ");
    }
}

image.png

剖析Arrays.sort

  • Arrays.sort能够提供排序的方法参数仅支持:int,long,short,char,byte,float,double
  • 其余的都列入Object类型,例如我们日常使用频率更高的包装类型:Integer等

以int[]数组为例:

  • 点进去方法,率先会进入到判断一个数值的区间,QUICKSORT_THRESHOLD = 286 image.png
  • 跳进去 sort 方法,则会再次进入一个判读,INSERTION_SORT_THRESHOLD = 47 image.png
  • 对于数组长度的不一样,Arrays.sort所使用的排序方式也不一样。
    • 长度小于286的,进入私有方法sort,并传参
      • 长度小于47的,使用插入排序的算法
      • 长度大于47的,使用快速排序的算法
    • 长度大于286的,判断是否已经具备结构化(排序接近完成),分组后判断使用归并排序算法。 image.png

Arrays.sort的优化

Arrays.sort方法,并不是单一的排序,而是根据内部的数组长度,选择更优化的排序算法,是快速排序、归并排序、插入排序的组合。其中对于归并排序以及判断是否结构化的细节会在后面的章节解析。

Arrays.sort()方法其实也是用到了策略模式,体现了拆分的思维理念,排序的基本步骤和算法是不变的。但是改变的是按什么排序,也就是上述所说的匿名内部类的倒序,也就是comparator,比较器的方法;排序的结果也是由comparator去决定的。这也就策略模式,由不同的比较器生成的排序方式就是不同的策略。