本固枝荣 —— Java比较器之Comparable接口和Comparator接口

目录

一、Comparable接口

二、Comparator接口

三、常见容器的排序API


一、Comparable接口

想要了解它的工作原理和功能,可以打开java.lang包下的Comparable接口源码,从类和方法的注释说明中,我们可以提取到重要的信息如下:

  1. Comparable接口对实现它的每个类都会赋予一种顺序,通过compareTo()方法实现自然排序;

  2. 自然排序的具体应用有:List列表的对象排序(Collections.sort) 、数组的对象排序(Arrays.sort)、对象作为Map的key进行排序(SortedMap,如TreeMap)、对象作为Set的元素进行排序(SortedSet,如TreeSet);

  3. e1.compareTo(e2) == 0 是与 e1.equals(e2) 表达的含义一致的,特别要注意e2为null时,会抛NPE;

  4. 例如:e1.compareTo(e2),compareTo()方法用于比较两个对象的大小,如果返回值为0,e1等于e2;如果返回值为正整数,e1大于e2,反之,e1小于e2;

  5. compareTo()方法比较两个对象时,要符合像equals()方法一样具有的自反性、对称型、传递性与一致性;

// 源码
public interface Comparable<T> {
    public int compareTo(T o);
}

小结一下:

Comparable接口只有一个compareTo()方法,实现了两个对象按自然顺序(如从小到大)进行排序,应用于Collection、Array、Map等容器对象的比较排序,可看作是一种内部比较器。

二、Comparator接口

Comparator接口是为了实现更多的更复杂类型的排序而设计的,该接口利用了Java8接口方法特性,默认了许多比较方法的实现。跟随源码注释,来解读一下该接口每个方法的具体用途:

  1. compare():自定义比较器的排序规则(如设置o1.getAxx - o2.getAxx)。该方法比较两个对象时也具有自反性、对称型、传递性与一致性;
  2. equals():判断两个比较器对象是否相等;
  3. reversed():将元素按降序排序;
  4. naturalOrder():静态方法,将元素按照自然顺序排序;
  5. reverseOrder():静态方法,将元素按降序排序,等同于naturalOrder().reversed();
  6. nullsFirst():静态方法,排序的元素存在null,将null排在最前面;
  7. nullsLast():静态方法,排序的元素存在null,将null排在最后面;
  8. comparing():静态方法,定义比较器比较规则,comparingXxx()针对比较对象中元素的不同类型(comparingInt()、comparingLong()、comparingDouble()等);
  9. thenComparing():与comparing()搭配使用,用于先比较....再比较....的场景。
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

    default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator<T> & Serializable) (c1, c2) -> {
            int res = compare(c1, c2);
            return (res != 0) ? res : other.compare(c1, c2);
        };
    }
    ......;

    public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }
    public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;
    }
    public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(true, comparator);
    }
    public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(false, comparator);
    }

    ......;
    public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }
    ......;
}

小结一下:

Comparator接口是一种外部比较器,通过自定义比较规则的形式进行排序,Java8对Comparator接口功能进行了很大的增强,常见于stream流式处理中排序的功能。

三、常见容器的排序API

Java中具有排序功能的容器数组Arrays、集合Collection(包括集合工具类Collections、其他实现类集合)、映射Map等等。

Arrays sort() API:

总的来看有下面四类排序API:(注:没有指定比较器的比较规则的,默认都是升序排序)

  1. sort(type []);  //按升序,对数组元素排序
  2. sort(type [], fromIndex, toIndex);  // 按升序,对数组指定范围[fromIndex,toIndex)内的元素排序
  3. sort(type [], Comparator c);  //按照比较器对象指定的规则,对数组元素排序
  4. parallelSort():为并行排序,拥有上述三种类型API,这是Java8新增的API,适用于大数据量的数组排序

Collections sort() API:

看源码可知,Collections排序调用的是List接口的sort()方法,是Java8新增的API,Collections核心的排序功能仍是通过Arrays.sort(a, (Comparator) c); 实现的。

  • sort(List<T> list);//按升序,对List集合元素排序

  • sort(List<T> list, Comparator<? super T> c);//按照比较器对象指定的规则,对List集合元素排序

ArrayList/LinkedList/Vector sort() API: 

  看源码可知,ArrayList集合 和 Vector集合在Java8新增了排序方法,本质上都是重写了List接口的sort()方法。

  • sort(Comparator<? super E> c);//按比较器对象指定的规则,对集合元素排序

TreeSet :按照默认的自然顺序,对TreeSet集合的元素进行排序。

TreeMap:按照默认的自然顺序,对TreeMap的key进行排序。

Java中实现Comparable接口的常见核心类:

  • String类;

  • 包装类型;

  • BigInteger与BigDecimal等大数值类

  • 枚举类等等

小结

从上述的分析来看,Comparable接口是一种自然顺序排序的接口,对未指定Comparator比较器规则的场景均默认按自然顺序排序,可理解为Comparable是一种内部比较器。而Comparator接口具有更自由的排序规则,根据不同的需求场景自定义排序,可理解为Comparator是一种外部比较器。Comparator接口在Java8进行了增强,重点放在了与stream流搭配使用时进行数据的高效处理,关于比较器的demo例子将在Java8系列整理中在写吧。不积硅步无以至千里,点滴付出终将有所收获,共同进步 ~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值