详解Java中Comparable和Comparator接口的区别
详解java中comparable和comparator接口的区别
本文要来详细分析一下java中comparable和comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的java开发者继续看下去吧。
comparable 简介
comparable 是排序接口。
若一个类实现了comparable接口,就意味着“该类支持排序”。 即然实现comparable接口的类支持排序,假设现在存在“实现comparable接口的类的对象的list列表(或数组)”,则该list列表(或数组)可以通过 collections.sort(或 arrays.sort)进行排序。
此外,“实现comparable接口的类的对象”可以用作“有序映射(如treemap)”中的键或“有序集合(treeset)”中的元素,而不需要指定比较器。
comparable 定义
comparable 接口仅仅只包括一个函数,它的定义如下:
package java.lang; import java.util.*; public interface comparable<t> { public int compareto(t o); }
说明:
假设我们通过 x.compareto(y) 来“比较x和y的大小”。若返回“负数”,意味着“x比y小”;返回“零”,意味着“x等于y”;返回“正数”,意味着“x大于y”。
comparator 简介
comparator 是比较器接口。
我们若需要控制某个类的次序,而该类本身不支持排序(即没有实现comparable接口);那么,我们可以建立一个“该类的比较器”来进行排序。这个“比较器”只需要实现comparator接口即可。
也就是说,我们可以通过“实现comparator类来新建一个比较器”,然后通过该比较器对类进行排序。
comparator 定义
comparator 接口仅仅只包括两个个函数,它的定义如下:
package java.util; public interface comparator<t> { int compare(t o1, t o2); boolean equals(object obj); }
说明:
(01) 若一个类要实现comparator接口:它一定要实现compareto(t o1, t o2) 函数,但可以不实现 equals(object obj) 函数。
为什么可以不实现 equals(object obj) 函数呢? 因为任何类,默认都是已经实现了equals(object obj)的。 java中的一切类都是继承于java.lang.object,在object.java中实现了equals(object obj)函数;所以,其它所有的类也相当于都实现了该函数。
(02) int compare(t o1, t o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
comparator 和 comparable 比较
comparable是排序接口;若一个类实现了comparable接口,就意味着“该类支持排序”。
而comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:comparable相当于“内部比较器”,而comparator相当于“外部比较器”。
我们通过一个测试程序来对这两个接口进行说明。源码如下:
import java.util.*; import java.lang.comparable; /** * @desc "comparator"和“comparable”的比较程序。 * (01) "comparable" * 它是一个排序接口,只包含一个函数compareto()。 * 一个类实现了comparable接口,就意味着“该类本身支持排序”,它可以直接通过arrays.sort() 或 collections.sort()进行排序。 * (02) "comparator" * 它是一个比较器接口,包括两个函数:compare() 和 equals()。 * 一个类实现了comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。 * * 综上所述:comparable是内部比较器,而comparator是外部比较器。 * 一个类本身实现了comparable比较器,就意味着它本身支持排序;若它本身没实现comparable,也可以通过外部比较器comparator进行排序。 */ public class comparecomparatorandcomparabletest{ public static void main(string[] args) { // 新建arraylist(动态数组) arraylist<person> list = new arraylist<person>(); // 添加对象到arraylist中 list.add(new person("ccc", 20)); list.add(new person("aaa", 30)); list.add(new person("bbb", 10)); list.add(new person("ddd", 40)); // 打印list的原始序列 system.out.printf("original sort, list:%s\n", list); // 对list进行排序 // 这里会根据“person实现的comparable<string>接口”进行排序,即会根据“name”进行排序 collections.sort(list); system.out.printf("name sort, list:%s\n", list); // 通过“比较器(ascagecomparator)”,对list进行排序 // ascagecomparator的排序方式是:根据“age”的升序排序 collections.sort(list, new ascagecomparator()); system.out.printf("asc(age) sort, list:%s\n", list); // 通过“比较器(descagecomparator)”,对list进行排序 // descagecomparator的排序方式是:根据“age”的降序排序 collections.sort(list, new descagecomparator()); system.out.printf("desc(age) sort, list:%s\n", list); // 判断两个person是否相等 testequals(); } /** * @desc 测试两个person比较是否相等。 * 由于person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。 * 所以,这里的p1和p2相等。 * * todo:若去掉person中的equals()函数,则p1不等于p2 */ private static void testequals() { person p1 = new person("eee", 100); person p2 = new person("eee", 100); if (p1.equals(p2)) { system.out.printf("%s equal %s\n", p1, p2); } else { system.out.printf("%s not equal %s\n", p1, p2); } } /** * @desc person类。 * person实现了comparable接口,这意味着person本身支持排序 */ private static class person implements comparable<person>{ int age; string name; public person(string name, int age) { this.name = name; this.age = age; } public string getname() { return name; } public int getage() { return age; } public string tostring() { return name + " - " +age; } /** * 比较两个person是否相等:若它们的name和age都相等,则认为它们相等 */ boolean equals(person person) { if (this.age == person.age && this.name == person.name) return true; return false; } /** * @desc 实现 “comparable<string>” 的接口,即重写compareto<t t>函数。 * 这里是通过“person的名字”进行比较的 */ @override public int compareto(person person) { return name.compareto(person.name); //return this.name - person.name; } } /** * @desc ascagecomparator比较器 * 它是“person的age的升序比较器” */ private static class ascagecomparator implements comparator<person> { @override public int compare(person p1, person p2) { return p1.getage() - p2.getage(); } } /** * @desc descagecomparator比较器 * 它是“person的age的升序比较器” */ private static class descagecomparator implements comparator<person> { @override public int compare(person p1, person p2) { return p2.getage() - p1.getage(); } } }
下面对这个程序进行说明。
a) person类定义。如下:
private static class person implements comparable<person>{ int age; string name; ... /** * @desc 实现 “comparable<string>” 的接口,即重写compareto<t t>函数。 * 这里是通过“person的名字”进行比较的 */ @override public int compareto(person person) { return name.compareto(person.name); //return this.name - person.name; } }
说明:
(01) person类代表一个人,persong类中有两个属性:age(年纪) 和 name“人名”。
(02) person类实现了comparable接口,因此它能被排序。
b) 在main()中,我们创建了person的list数组(list)。如下:
// 新建arraylist(动态数组) arraylist<person> list = new arraylist<person>(); // 添加对象到arraylist中 list.add(new person("ccc", 20)); list.add(new person("aaa", 30)); list.add(new person("bbb", 10)); list.add(new person("ddd", 40));
c) 接着,我们打印出list的全部元素。如下:
// 打印list的原始序列 system.out.printf("original sort, list:%s\n", list);
d) 然后,我们通过collections的sort()函数,对list进行排序。
由于person实现了comparable接口,因此通过sort()排序时,会根据person支持的排序方式,即 compareto(person person) 所定义的规则进行排序。如下:
// 对list进行排序 // 这里会根据“person实现的comparable<string>接口”进行排序,即会根据“name”进行排序 collections.sort(list); system.out.printf("name sort, list:%s\n", list);
e) 对比comparable和comparator
我们定义了两个比较器 ascagecomparator 和 descagecomparator,来分别对person进行 升序 和 降低 排序。
e.1) ascagecomparator比较器
它是将person按照age进行升序排序。代码如下:
/** * @desc ascagecomparator比较器 * 它是“person的age的升序比较器” */ private static class ascagecomparator implements comparator<person> { @override public int compare(person p1, person p2) { return p1.getage() - p2.getage(); } }
e.2) descagecomparator比较器
它是将person按照age进行降序排序。代码如下:
/** * @desc descagecomparator比较器 * 它是“person的age的升序比较器” */ private static class descagecomparator implements comparator<person> { @override public int compare(person p1, person p2) { return p2.getage() - p1.getage(); } }
f) 运行结果
运行程序,输出如下:
original sort, list:[ccc - 20, aaa - 30, bbb - 10, ddd - 40] name sort, list:[aaa - 30, bbb - 10, ccc - 20, ddd - 40] asc(age) sort, list:[bbb - 10, ccc - 20, aaa - 30, ddd - 40] desc(age) sort, list:[ddd - 40, aaa - 30, ccc - 20, bbb - 10] eee - 100 equal eee - 100
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
上一篇: MySql游标的使用实例
推荐阅读
-
详解Java中Comparable和Comparator接口的区别
-
Java中Object.equals和String.equals的区别详解
-
java中实现Comparable接口实现自定义排序的示例
-
Java中弱引用和软引用的区别以及虚引用和强引用介绍
-
Java中HashTable和HashMap的区别_动力节点Java学院整理
-
Java中HashSet和HashMap的区别_动力节点Java学院整理
-
java中重载,继承,重写和多态的区别
-
java 数据结构中栈和队列的实例详解
-
java中 String和StringBuffer的区别实例详解
-
java 中 System.out.println()和System.out.write()的区别