13-Java中Comparable和Comparator的区别?
下面分别对Comparable 和 Comparator做具体介绍并总结。
Comparable
Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较,则依赖compareTo方法的实现。
如果add进入一个Collection的对象想要Collections的sort方法帮你自动进行排序的话,那么这个对象必须实现Comparable接口。compareTo方法的返回值是int,有三种情况:
-
比较者大于被比较者,返回正整数
-
比较者等于被比较者,返回0
-
比较者小于被比较者,返回负整数
写个很简单的例子:
/** * 实现Comparable重写compareTo方法进行Person的排序, 这里根据年龄排序 * * @author * @date */ @Getter @Setter @ToString @AllArgsConstructor @NoArgsConstructor public class Person implements Comparable<Person> { private String name; private int age; @Override public int compareTo(Person p) { // return p.getAge() - this.getAge() return this.getAge() - p.getAge(); } }
public class Demo { public static void main(String[] args) { Person p1 = new Person("aaa", 11); Person p2 = new Person("bbb", 5); Person p3 = new Person("cc", 8); Person[] ps = {p1, p2, p3}; System.out.println(Arrays.toString(ps)); // 排序前 Arrays.sort(ps); System.out.println(Arrays.toString(ps)); // 排序后 System.out.println("----------------"); Map<Person, String> map = new TreeMap<>(); map.put(p1, "aaa"); map.put(p2, "bbb"); map.put(p3, "ccc"); System.out.println(map.toString()); System.out.println("----------------"); List<Person> list = new ArrayList<>(); list.add(p1); list.add(p2); list.add(p3); Collections.sort(list); // 排序 System.out.println(list.toString()); } }
执行结果:
[Person(name=aaa, age=11), Person(name=bbb, age=5), Person(name=cc, age=8)] [Person(name=bbb, age=5), Person(name=cc, age=8), Person(name=aaa, age=11)] ---------------- {Person(name=bbb, age=5)=bbb, Person(name=cc, age=8)=ccc, Person(name=aaa, age=11)=aaa} ---------------- [Person(name=bbb, age=5), Person(name=cc, age=8), Person(name=aaa, age=11)]
Comparator
Comparator接口里面有一个compare方法,方法有两个参数T o1和T o2,是泛型的表示方式,分别表示待比较的两个对象,方法返回值和Comparable接口一样是int,有三种情况:
-
o1大于o2,返回正整数
-
o1等于o2,返回0
-
o1小于o3,返回负整数
写个很简单的例子:
public class ComparatorDemo { public static void main(String[] args) { /** * 按照数组元素长度排序 */ String[] str = {"abcdeftg", "maidi", "kebi", "zhanmusi"}; Arrays.sort(str, new Comparator<String>() { public int compare(String o1, String o2) { return o1.length() - o2.length(); } }); System.out.println(Arrays.toString(str)); }
这里的Arrays.sort对数组进行排序用到了Compartor接口, 上面使用了匿名函数的写法, 也可以使用lambda进行改造...
Arrays.sort(str, (o1, o2) -> o1.length() - o2.length());
一行代码就可以搞定, 的确很简单
运行结果
[kebi, maidi, abcdeftg, zhanmusi]
因为泛型指定死了,所以实现Comparator接口的实现类只能是两个相同的对象(不能一个自定义对象、一个String)进行比较,实现Comparator接口的实现类一般都会以"待比较的实体类+Comparator"来命名, 只不过这里使用了匿名函数更简单而已
总结
上面的例子不管是Comparable还是Comparator, 都是按照升序来排序的, 如果想要按照反过来的顺序, 改改代码即可, 只需要修改接口中的实现方法, 调换一下相减的两个比较对象或者值即可, 例如"// return p.getAge() - this.getAge()"注释掉的代码那里一样
如果实现类没有实现Comparable接口,又想对两个类进行比较(或者实现类实现了Comparable接口,但是对compareTo方法内的比较算法不满意),那么可以实现Comparator接口,自定义一个比较器,写比较算法。
实现Comparable接口的方式比实现Comparator接口的耦合性要强一些,如果要修改比较算法,要修改Comparable接口的实现类,而实现Comparator的类是在外部进行比较的,不需要对实现类有任何修改。因此:
-
对于一些普通的数据类型(比如 String, Integer, Double…),它们默认实现了Comparable 接口,实现了 compareTo 方法,我们可以直接使用。
-
而对于一些自定义类,它们可能在不同情况下需要实现不同的比较策略,我们可以新创建 Comparator 接口,然后使用特定的 Comparator 实现进行比较。
不同之处:
实现Comparable接口的方式比实现Comparator接口的耦合性要强
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)