Arrays.sort自定义排序原理探索

303 阅读1分钟

最近用到Arrays.sort时想到一个问题,重写的compare方法里返回-1,和1是怎么影响排序的,所以今儿咱就来看看 先看下面这个例子:

Man[] human = { new Man(3, "a"), new Man(60, "b"), new Man(2, "c") };
Arrays.sort(human,new Comparator<Man>(){

    @Override
    public int compare(Man o1, Man o2) {
        if (o1.age<o2.age){
            return 1;
        }else if (o1.age>o2.age){
            return -1;
        }
        return 0;
    }
});
for(Man man:human){
    System.out.println(man.age);
}

我们点进Arrays.sort方法,

public static <T> void sort(T[] a, Comparator<? super T> c) {
    if (c == null) {
        sort(a);
    } else {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a, c);
        else
            TimSort.sort(a, 0, a.length, c, null, 0, 0);
    }
}

LegacyMergeSort是jdk1.6老板本用的排序,未来会被移除.用的是冒泡和归并. 没有配置过这个参数的话就走TimSort. 关于TimSort,有兴趣可以搜搜看,大致就是使用插排和归并来优化排序,使用一个个单调的run(分区)调整为递增,合并等等。

if (runLen < minRun) {
    int force = nRemaining <= minRun ? nRemaining : minRun;
    binarySort(a, lo, lo + force, lo + runLen, c);
    runLen = force;
}

nextrun的len小于minRun,使用插排使其达到最小分区长度。

while (left < right) {
    int mid = (left + right) >>> 1;
    if (c.compare(pivot, a[mid]) < 0)
        right = mid;
    else
        left = mid + 1;
}

这里compare会走我们自定义的,pivot为区间的右端,只有pivot小于a[mid]才会走right=mid,所以我们知道当返回-1时,o1.age>o2.age,后面的小是什么情况呢?当然是降序,这也就解决了开始的问题,返回1和-1为什么能控制对象的升降序。