Comparable与Comparator的区别
说明:对一组数据进行排序(升序或降序),在Java中有很多方式,可以自己手写排序算法(冒泡、快速、二叉树排序等),但一般都采用JDK为我们提供的现有的2个接口,Comparable和Comparator。
【二者的区别】
Comparable接口:
-
可作为实现类的默认排序算法
-
Java中一些普通的数据类型(比如String,Integer,Double…),已经默认实现了Comprable接口,实现了compareTo方法,我们可以直接使用
Comprator接口:
-
是一个类的扩展排序工具,采用策略模式
-
对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,可以新创建Comparator接口,使用特定的Comparator实现进行比较
-
可用于Collection.sort()、Arrays.sort()或者一些内部有序的集合(如SortedSet、SortedMap等)
【注意点】
-
同时存在,采用Comparator的规则进行比较
-
Comparble接口的compareTo方法的返回值有3种情况:
- e1.compareTo(e2) > 0 即 e1 > e2
- e1.compareTo(e2) = 0 即 e1 = e2
- e1.compareTo(e2) < 0 即 e1 < e2
通俗来说,如果一个实体类实现了Comparable接口来实现排序规则,使用一段时间后,如果想去改变这个排序规则,基于“开闭原则”对修改关闭对扩展开放,我们可以通过Comparator接口来实现新的排序规则让实体类去采纳,使用一段时间后,如果还想改变,再通过Comparator接口实现一个新的排序规则即可。不影响类的封装性,易于扩展。
【例子】
实体类BookBean实现了Comparable接口,比较规则是按书价大小。将多个BookBean对象存储在List容器中,存储顺序是按照compareTo的规则。
//实体类
public class BookBean implements Comparable{
//书名
private String name;
//书价
private int count;
//省略带参的构造函数、setter-getter方法、toString方法
@Override
public int compareTo(Object another) {
if(another instanceof BookBean){
BookBean anotherBook = (BookBean) another;
int result;
//这里按照书价比较
result = getCount() - anotherBook.getCount();
}
return 0;
}
}
public class Demo{
public static void main(String[] args) {
List<BookBean> list = new ArrayList<>();
list.add(new BookBean("A",34));
list.add(new BookBean("S",1));
list.add(new BookBean("V",46));
list.add(new BookBean("Q",26));
//对list容器排序:按照内部存储对象BookBean的比较规则
Collections.sort(list);
//输出第一个元素
System.out.println(list.get(0));
}
}
测试结果:结果表明是按照书价大小来排序。
针对上述例子,此时如果想改变排序规则,在不破坏原实体类的封装性的前提下,可实现Comparator接口制定新规则,在Collections.sort(list,comparator)中传入参数调用。
public class Demo2{
public static void main(String[] args) {
List<BookBean> list = new ArrayList<>();
list.add(new BookBean("A",34));
list.add(new BookBean("S",1));
list.add(new BookBean("V",46));
list.add(new BookBean("Q",26));
//新增代码
Comparator comparator1 = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof NewBookBean && o2 instanceof NewBookBean){
NewBookBean newBookBean1 = (NewBookBean) o1;
NewBookBean newBookBean2 = (NewBookBean) o2;
//这里还调用了 String 实现了Comparable 接口的 compareTo 方法,内部是通过 char 字符逐字比较使得
//排序方式:按书名的字符串升序排序
return newBookBean1.getName().compareTo(newBookBean2.getName());
}
return 0;
}
};
//对list容器排序,传入comparator:按照内部存储对象BookBean的比较规则
Collections.sort(list,comparator1);
//Collections.sort(list);
//输出第一个元素
System.out.println(list.get(0));
}
}
测试结果:结果表明是按照书名字符大小来排序的。
【总结】
这回知道二者的区别,以及怎么去使用了,开心!
参考文章:
1.https://blog.csdn.net/lck898989/article/details/78881330
2.https://blog.csdn.net/u011240877/article/details/53399019