#案例+源码分析# Comparator.compare方法,-1,0,1是升序还是降序?

Comparator接口,用于比较两个数,通过比较的结果,进行排序。参数1<、=、>参数2的时候,分别返回-1、0、1。

那么,问题来了,当返回-1的时候,是升序排列,还是降序排列?

通过一段代码,我们来追踪源码分析一波~

对于下面这个Map,key为数据库字段名,List<String>是该字段的所有历史取值。需求:将每个字段的历史取值,按照取值的长短进行排序,长的在前、短者在后。

Map<String, List<String>> history = new HashMap<>();

如下代码,即可满足上面的要求:(整个代码结合了Stream流式操作、lambda表达式,不会的童鞋可以补一波)

    // 历史记录按照取值的长短进行排序,长前短后
    historyLocal.forEach((field, historyValues) -> {
        historyValues.sort(((o1, o2) -> {
            if (o1.length() > o2.length()) {
                return -1;
            } else if (o1.length() < o2.length()) {
                return 1;
            }
            return 0;
        }));
        history.put(field, historyValues);
    });

结合上面的代码,我们来分析一波排序的底层源码。

 摁住Ctrl键,点击上面的箭头->,可以发现,我们跳转到了Comparator接口类。这表明,sort方法内部的lambda表达式,其实是对以下compare()方法的具体实现,制定了排序的规则。

    public interface Comparator<T> {
        int compare(T o1, T o2);
    }

sort()方法则根据compare(T o1, T o2)的返回结果(-1、0、1)进行排序。进入sort()方法,我们可以看到以下代码:

    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }

这是List接口的默认方法(不清楚默认方法的,可以百度一波哈),从代码可以看出,排序操作主要由Arrays.sort(a, (Comparator) c)实现。进入方法内部,有:

    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(a, c)方法内部,有:

    private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
        T[] aux = a.clone();
        if (c==null)
            mergeSort(aux, a, 0, a.length, 0);
        else
            mergeSort(aux, a, 0, a.length, 0, c);
    }

再点击进入mergeSrot(aux, a, 0, a.length, 0, c)方法内部,有:

    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low, int high, int off,
                                  Comparator c) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // 省略无关代码
    }

答案便在这了:

    for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
        swap(dest, j, j-1);

可以看出,当前者与后者的比较,compare方法返回1时,则将二者进行交换。回顾我们写的lambda表达式:

    historyValues.sort(((o1, o2) -> {
        if (o1.length() > o2.length()) {
            return -1;
        } else if (o1.length() < o2.length()) {
            return 1;
        }
        return 0;
    }));

当o1的长度<o2的长度,则返回1。也就是说,前者长度<后者长度时,则进行位置的交换,这也就实现了“长者在前、短者在后”的效果。

总结

不论比较的具体规则是什么,按照-1、0、1的顺序进行排序。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的Coder*

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值