5

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

 1 year ago
source link: https://www.cnblogs.com/JavaBuild/p/18030265
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

Comparable

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

【源码解析1】

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

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

@Datapublic 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(); }}

写一个测试类,调用

【代码示例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<T> { int compare(T o1, T o2); boolean equals(Object obj);}

讲到这里,我们可以对比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(); }}

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()); } }}

输出:

小华小明

我们跟进去看一下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++;}

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

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

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

3271023-20240223193646059-14686519.png

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK