• 面试官:你知道Comparable 和 Comparator 的区别吗?我:巴拉巴拉


    写在开头

    面试官:“我们在Java的集合和数据结构中都离不开比较器,请你聊一聊Comparable 和 Comparator 这两种的区别吧”
    内心活动:“上来就这么直接吗,那些ArrayList,HashMap都不问呀,好,既然如此,那让我来征服你吧,面试官大人!”
    我:“好滴!巴拉巴拉~”

    Comparable

    Comparable是java.lang包下的一个接口,其内部构造非常简单,只有一个compareTo()方法,使用起来也很简单,直接实现接口,重写方法即可。

    【源码解析1】

    public interface Comparable {
    int compareTo(T t);
    }

    【代码示例1】
    定义一个Person类,重写compareTo()方法,用以比较Person对象的年龄大小

    @Data
    public class Person implements Comparable{
    private int age;
    private String name;
    public Person(int age, String name) {
    this.age = age;
    this.name = name;
    }
    @Override
    public int compareTo(Person o) {
    return this.getAge()-o.getAge();
    }
    }

    写一个测试类,调用

    【代码示例2】

    public class Test {
    public static void main(String[] args) {
    Person xiaoming = new Person(18, "小明");
    Person xiaohua = new Person(20, "小华");
    if(xiaoming.compareTo(xiaohua) <0){
    System.out.println(xiaoming.getName()+"更年轻");
    }else{
    System.out.println(xiaohua.getName()+"更年轻");
    }
    }
    }

    输出:

    小明更年轻

    以上是我们自己实现的Comparable接口,其实在Java中像String、基本类型的包装类在底层也都实现了这个接口,并重写了compareTo()方法,因此,他们也拥有比较属性。

    【代码示例3】

    Integer in1 = 2;
    Integer in2 = 3;
    System.out.println(in1.compareTo(in2));

    输出:

    -1

    Comparator

    Comparator 是java.util包中的一个接口,它的底层构造相比较Comparable要复杂的多了,不过我们主要还是关注其中的compare()方法。

    【源码解析2】

    public interface Comparator {
    int compare(T o1, T o2);
    boolean equals(Object obj);
    }

    讲到这里,我们可以对比Comparable接口进行阐述,解释一下为什么有个相似的比较排序接口,还要设计Comparator,因为很多时候我们并不想破坏原始类的结构,比如Person类中,我们只需要它拥有age和name,不想写一些实现方法在其中,这个时候就需要Comparator啦!

    1)首先,我们可以为Person类自定义一个比较器

    【代码示例4】

    public class PersonalComparator implements Comparator {
    @Override
    public int compare(Person o1, Person o2) {
    return o1.getAge() - o2.getAge();
    }
    }

    2)然后,我们写一个测试类使用一下看看,其实这里面要借助一个List的sort()进行调用,我们直接手撕代码,这样更容易理解!

    【代码示例5】

    public class Test {
    public static void main(String[] args) {
    Person xiaoming = new Person(20, "小明");
    Person xiaohua = new Person(18, "小华");
    ArrayList objects = new ArrayList<>();
    objects.add(xiaoming);
    objects.add(xiaohua);
    objects.sort(new PersonalComparator());
    for (Person object : objects) {
    System.out.println(object.getName());
    }
    }
    }

    输出:

    小华
    小明

    我们跟进去看一下sort()方法的底层源码,会发现,在它的底层实际上Arrays.sort进行数组排序,而使用的比较器,就是我们传入的自定义PersonalComparator 对象。

    【源码解析3】

    public void sort(Comparatorsuper E> c) {
    // 保存当前队列的 modCount 值,用于检测 sort 操作是否非法
    final int expectedModCount = modCount;
    // 调用 Arrays.sort 对 elementData 数组进行排序,使用传入的比较器 c
    Arrays.sort((E[]) elementData, 0, size, c);
    // 检查操作期间 modCount 是否被修改,如果被修改则抛出并发修改异常
    if (modCount != expectedModCount) {
    throw new ConcurrentModificationException();
    }
    // 增加 modCount 值,表示队列已经被修改过
    modCount++;
    }

    好了,解释到这里,我想已经足以令面试官满意了,两者的底层实现,如何使用都进行了详细的阐述,但是!如果你足够自信,可以进一步延伸出Collections.sort(),它的底层其实也是比较器,只不过这个比较器没有特殊的实现,采用的自然排序规则(升序)。源码就不在这里展示了,爱钻研的小伙伴可以自己去看哈。

    二者比较

    1、一个类实现了 Comparable,意味着该类的对象可以直接进行比较(排序)
    但比较(排序)的方式只有一种,很单一。
    2、一个类如果想要保持原样,又需要进行不同方式的比较(排序),
    就可以定制比较器(实现 Comparator 接口)。
    3、Comparable 接口在 java.lang 包下,
    而 Comparator 接口在 java.util 包下。

    结尾彩蛋

    如果本篇博客对您有一定的帮助,大家记得留言+点赞+收藏呀。原创不易,转载请联系Build哥!

  • 相关阅读:
    OAK相机:启动报错X_LINK_DEVICE_NOT_FOUND
    字符串相关算法
    PowerDesginer提示打印机错误
    论文阅读之《Kindling the Darkness: A Practical Low-light Image Enhancer》
    按照型号分组,分组后统计数量
    FFmpeg5开发入门教程18:解码内存数据并播放
    4.7k Star!全面的C#/.NET/.NET Core学习、工作、面试指南
    Springboot+vue的时间管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。
    Azure考试认证经验
    (※)力扣刷题-字符串-实现 strStr()(KMP算法)
  • 原文地址:https://www.cnblogs.com/JavaBuild/p/18030265