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

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

写在开头

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

Comparable

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

【源码解析1】

public interface Comparable<T> {
   
    int compareTo(T t);
}
AI 代码解读

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

@Data
public class Person implements Comparable<Person>{
   

    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();
    }
}
AI 代码解读

写一个测试类,调用

【代码示例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()+"更年轻");
        }
    }
}
AI 代码解读

输出:

小明更年轻
AI 代码解读

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

【代码示例3】

Integer in1 = 2;
Integer in2 = 3;
System.out.println(in1.compareTo(in2));
AI 代码解读

输出:

-1
AI 代码解读

Comparator

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

【源码解析2】

public interface Comparator<T> {
   
    int compare(T o1, T o2);
    boolean equals(Object obj);
}
AI 代码解读

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

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

【代码示例4】

public class PersonalComparator implements Comparator<Person> {
   

    @Override
    public int compare(Person o1, Person o2) {
   
        return o1.getAge() - o2.getAge();
    }
}
AI 代码解读

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

【代码示例5】

public class Test {
   
    public static void main(String[] args) {
   
        Person xiaoming = new Person(20, "小明");
        Person xiaohua = new Person(18, "小华");

        ArrayList<Person> objects = new ArrayList<>();
        objects.add(xiaoming);
        objects.add(xiaohua);

        objects.sort(new PersonalComparator());

        for (Person object : objects) {
   
            System.out.println(object.getName());
        }
    }
}
AI 代码解读

输出:

小华
小明
AI 代码解读

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

【源码解析3】

public void sort(Comparator<? super 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++;
}
AI 代码解读

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

二者比较

1、一个类实现了 Comparable,意味着该类的对象可以直接进行比较(排序)
但比较(排序)的方式只有一种,很单一。

2、一个类如果想要保持原样,又需要进行不同方式的比较(排序),
就可以定制比较器(实现 Comparator 接口)。

3、Comparable 接口在 java.lang 包下,
而 Comparator 接口在 java.util 包下。
AI 代码解读
目录
打赏
0
1
1
0
66
分享
相关文章
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
111 9
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
96 12
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
Lambda表达式和匿名函数都是Kotlin中强大的特性,帮助开发者编写简洁而高效的代码。理解它们的区别和适用场景,有助于选择最合适的方式来解决问题。希望本文的详细讲解和示例能够帮助你在Kotlin开发中更好地运用这些特性。
50 9
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
今日分享的主题是如何区分&和&&的区别,提高自身面试的能力。主要分为以下四部分。 1、自我面试经历 2、&amp和&amp&amp的不同之处 3、&对&&的不同用回答逻辑解释 4、彩蛋
Java社招面试题:& 和 && 的区别,HR的套路险些让我翻车!
小米,29岁程序员,分享了一次面试经历,详细解析了Java中&和&&的区别及应用场景,展示了扎实的基础知识和良好的应变能力,最终成功获得Offer。
120 14
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点、状态码、报文格式,GET、POST的区别,DNS的解析过程、数字证书、Cookie与Session,对称加密和非对称加密
经典面试题:变量的声明和定义有什么区别
在编程领域,变量的“声明”与“定义”是经典面试题之一。声明告诉编译器一个变量的存在,但不分配内存,通常包含变量类型和名称;而定义则为变量分配内存空间,一个变量必须至少被定义一次。简而言之,声明是告知变量形式,定义则是实际创建变量并准备使用。
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
本文阐述了Spring、Spring Boot和Spring MVC的关系与区别,指出Spring是一个轻量级、一站式、模块化的应用程序开发框架,Spring MVC是Spring的一个子框架,专注于Web应用和网络接口开发,而Spring Boot则是对Spring的封装,用于简化Spring应用的开发。
413 0
Spring,SpringBoot和SpringMVC的关系以及区别 —— 超准确,可当面试题!!!也可供零基础学习
面试官:px、em、rem、vw、rpx 之间有什么区别?
面试官:px、em、rem、vw、rpx 之间有什么区别?
141 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等