关于Comparable和Comparator的联系和区别,我们先实现这个两个接口。
package com.blb.考前;
public class Demo02 implements Comparable<Demo02> {
@Override
public int compareTo(Demo02 o) {
// TODO Auto-generated method stub
return 0;
}
}
package com.blb.考前;
import java.util.Comparator;
public class Demo03 implements Comparator<Demo03> {
@Override
public int compare(Demo03 o1, Demo03 o2) {
// TODO Auto-generated method stub
return 0;
}
}
最直观的感受就是Comparator需要导包但是Comparable却不需要。
通过这两幅图片我们可以清晰的观察到这两个接口来的位置,一个是在java.lang,一个是在java.util这个就是为什么有一个需要导包而另外一个不需要的原因。
我们可以看到在Comparable接口中重写的方法中:
@Override
public int compareTo(Demo02 o) {
// TODO Auto-generated method stub
return 0;
}
每次只需要传入一个参数,因为这个方法就在本类中每次传入的形参就是本类的对象,可以理解为一个内置的比较器内部的成员会自己比较。我们称这个排序为“自然排序”。比较规则就是:
- e1.compareTo(e2) > 0 即 e1 > e2
- e1.compareTo(e2) = 0 即 e1 = e2
- e1.compareTo(e2) < 0 即 e1 < e2
当返回值大于0是那么传入的第一个参数就是大于第二个参数以此类推。
实现了 Comparable 接口的 List 或则数组可以使用 Collections.sort() 或者 Arrays.sort() 方法进行排序。
实现了 Comparable 接口的对象才能够直接被用作 SortedMap (SortedSet) 的 key,要不然得在外边指定 Comparator 排序规则。实际上我们发现这些这些集合或者数组之所以可以排序,都是实现了这个Comparable 接口做到了可以在本类中实现排序。
很明显Comparator实现在一个外部类中,要求传入两个参数。
@Override
public int compare(Demo03 o1, Demo03 o2) {
// TODO Auto-generated method stub
return 0;
}
那么在这个类中我们完全可以实现自己所要表达的排序,我们可以称这个为定制排序。
通过这两幅图我们应该可以清楚的看到比较器应该如何引用。相当于当我们要排序一个自定义的数组类型时,我们用Arrays的sort方法这个就会有一个参数就是会要求传入一个自定义的比较器,这个我们就明白了自定义比较器的使用场景。
Comparable 自然排序。(实体类实现)
Comparator 是定制排序。(无法修改实体类时,直接在调用方创建)
对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。
但是当我们创建一个自己定义的数据类型时,又不是一个很简单排序策略时,我们就可以自己定义一个排序策略,在Comparator接口中实现。说白了就是默认的只能比较从大大小或者从小到大无法产生更复杂的排序策略。
这就是 Comparable 和 Comparator 的区别。