先看这两个接口最明显的区别:参数的个数不同
public interface Comparable<T> {
public int compareTo(T o);//一个参数
}
public interface Comparator<T> {
int compare(T o1, T o2);//两个参数
}
Comparable英文意思:可以比较的。自身就是有比较需求的,那么就可以实现Comparable。(俗称:内比较器)
Comparator英文意思:比较器。帮别人作比较的。(俗称:外比较器)
那要怎么用呢?
举个例子:假如你是一个歌手Singer:
class Singer{
private String name;//歌手的名字
//getter、setter
}
你是薛之谦的话,那么你要不要和另一个歌手曾轶可比谁的歌好听。你觉得这个没有意义,对吧!每个人喜欢听的歌、类型都不一样,只要你能抒发自己内心的情感,可以感染听众,你就很开心很满足了。
于是,歌手自身是没有比较需求的。
所以,Singer不会去继承Comparable。
但是你是音乐播放器的话,你就不会这样想了。你要将歌手排序“adc...xyz”到列表中给用户听啊!
于是,你就想要是Single继承了Comparable就好了。你准备改人家Single的代码,让Singer去继承Comparable接口。可是曾轶可不答应啊,人家想要风格简约一点,要简洁美。
这时候你就想到要用外比较器Comparator了,不改你的代码,我照样可以作比较。
public class SingerComparator implements Comparator<Singer>{
@Override
public int compare(Singer singer1, Singer singer2) {
return singer1.getName().compareTo(singer2.getName());//String自身有比较需求,所以人家实现了Comparable
}
}
TreeMap是有序的,它就继承了外比较器,因为它有帮别人作比较的需求。看下源码:
// private final Comparator<? super K> comparator;
// public TreeMap(Comparator<? super K> comparator) {
// this.comparator = comparator;
// }
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
这时候你就可以这样调用啦!
TreeMap<Singer, Object> treeMap = new TreeMap<>(new SingerComparator());
这样treeMap put一个Singer,就会自己排序啦!(put方法内部会调用上面的compare方法)
不知道你注意没有,上面一段代码:(Comparable<? super K>)k1).compareTo((K)k2,意思就是说:你没有给人家TreeMap初始化Comparator,comparator==null,那你自己的Single就必须实现Comparable,这样k1、k2才可以调用compareTo方法。
如果Singer没有实现Comparable,Comparator也没有传给TreeMap。这句(Comparable<? super K>)k1强转就要报错了。
Exception in thread "main" java.lang.ClassCastException: xxxx.Singer cannot be cast to java.lang.Comparable
你会用了吗^_^
---------------------
【转载,仅作分享,侵删】
作者:river66
原文:https://blog.csdn.net/river66/article/details/87865911
版权声明:本文为博主原创文章,转载请附上博文链接!
|
|