In this article, the two interfaces Comparable and Comparator are introduced first , and their differences; then, the usage of them is explained through examples.
Introduction to Comparables
Comparable is the sorting interface.
If a class implements the Comparable interface, it means " this class supports sorting ". Now that the class implementing the Comparable interface supports sorting, assuming that there is now a "List (or array) of objects of the class implementing the Comparable interface", the List (or array) can be sorted by Collections.sort (or Arrays.sort) sort.
In addition, an "object of a class implementing the Comparable interface" can be used as a key in an "ordered map (such as a TreeMap)" or as an element in an "ordered set (TreeSet)" without specifying a comparator.
Comparable Definition
The Comparable interface contains only one function, which is defined as follows:
package java.lang; import java.util. * ; public interface Comparable<T> { public int compareTo(T o); }
Explanation:
Suppose we "compare the size of x and y" via x.compareTo(y). If it returns "negative", it means "x is smaller than y"; if it returns "zero", it means "x is equal to y"; if it returns "positive", it means "x is greater than y".
Introduction to Comparator
Comparator is the comparator interface.
If we need to control the order of a class, and the class itself does not support sorting (that is, it does not implement the Comparable interface); then, we can create a "comparator of this class" to sort. This "comparator" only needs to implement the Comparator interface.
That is, we can " implement the Comparator class to create a new comparator ", and then sort the classes by that comparator.
Comparator Definition
The Comparator interface only includes two functions, which are defined as follows:
package java.util; public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
Description:
(01) If a class wants to implement the Comparator interface: it must implement the compareTo(T o1, T o2) function, but it may not implement the equals(Object obj) function.
Why not implement the equals(Object obj) function? Because any class, by default, has implemented equals(Object obj). All classes in Java are inherited from java.lang.Object, and the equals(Object obj) function is implemented in Object.java; therefore, all other classes are equivalent to implementing this function.
(02) int compare(T o1, T o2) 是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
Comparator 和 Comparable 比较
Comparable是排序接口;若一个类实现了Comparable接口,就意味着“该类支持排序”。
而Comparator是比较器;我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
我们不难发现:Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
我们通过一个测试程序来对这两个接口进行说明。源码如下:
1 import java.util.*; 2 import java.lang.Comparable; 3 4 /** 5 * @desc "Comparator"和“Comparable”的比较程序。 6 * (01) "Comparable" 7 * 它是一个排序接口,只包含一个函数compareTo()。 8 * 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。 9 * (02) "Comparator" 10 * 它是一个比较器接口,包括两个函数:compare() 和 equals()。 11 * 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。 12 * 13 * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。 14 * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。 15 */ 16 public class CompareComparatorAndComparableTest{ 17 18 public static void main(String[] args) { 19 // 新建ArrayList(动态数组) 20 ArrayList<Person> list = new ArrayList<Person>(); 21 // 添加对象到ArrayList中 22 list.add(new Person("ccc", 20)); 23 list.add(new Person("AAA", 30)); 24 list.add(new Person("bbb", 10)); 25 list.add(new Person("ddd", 40)); 26 27 // 打印list的原始序列 28 System.out.printf("Original sort, list:%s\n", list); 29 30 // 对list进行排序 31 // 这里会根据“Person实现的Comparable<String>接口”进行排序,即会根据“name”进行排序 32 Collections.sort(list); 33 System.out.printf("Name sort, list:%s\n", list); 34 35 // 通过“比较器(AscAgeComparator)”,对list进行排序 36 // AscAgeComparator的排序方式是:根据“age”的升序排序 37 Collections.sort(list, new AscAgeComparator()); 38 System.out.printf("Asc(age) sort, list:%s\n", list); 39 40 // 通过“比较器(DescAgeComparator)”,对list进行排序 41 // DescAgeComparator的排序方式是:根据“age”的降序排序 42 Collections.sort(list, new DescAgeComparator()); 43 System.out.printf("Desc(age) sort, list:%s\n", list); 44 45 // 判断两个person是否相等 46 testEquals(); 47 } 48 49 /** 50 * @desc 测试两个Person比较是否相等。 51 * 由于Person实现了equals()函数:若两person的age、name都相等,则认为这两个person相等。 52 * 所以,这里的p1和p2相等。 53 * 54 * TODO:若去掉Person中的equals()函数,则p1不等于p2 55 */ 56 private static void testEquals() { 57 Person p1 = new Person("eee", 100); 58 Person p2 = new Person("eee", 100); 59 if (p1.equals(p2)) { 60 System.out.printf("%s EQUAL %s\n", p1, p2); 61 } else { 62 System.out.printf("%s NOT EQUAL %s\n", p1, p2); 63 } 64 } 65 66 /** 67 * @desc Person类。 68 * Person实现了Comparable接口,这意味着Person本身支持排序 69 */ 70 private static class Person implements Comparable<Person>{ 71 int age; 72 String name; 73 74 public Person(String name, int age) { 75 this.name = name; 76 this.age = age; 77 } 78 79 public String getName() { 80 return name; 81 } 82 83 public int getAge() { 84 return age; 85 } 86 87 public String toString() { 88 return name + " - " +age; 89 } 90 91 /** 92 * 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等 93 */ 94 boolean equals(Person person) { 95 if (this.age == person.age && this.name == person.name) 96 return true; 97 return false; 98 } 99 100 /** 101 * @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。 102 * 这里是通过“person的名字”进行比较的 103 */ 104 @Override 105 public int compareTo(Person person) { 106 return name.compareTo(person.name); 107 //return this.name - person.name; 108 } 109 } 110 111 /** 112 * @desc AscAgeComparator比较器 113 * 它是“Person的age的升序比较器” 114 */ 115 private static class AscAgeComparator implements Comparator<Person> { 116 117 @Override 118 public int compare(Person p1, Person p2) { 119 return p1.getAge() - p2.getAge(); 120 } 121 } 122 123 /** 124 * @desc DescAgeComparator比较器 125 * 它是“Person的age的升序比较器” 126 */ 127 private static class DescAgeComparator implements Comparator<Person> { 128 129 @Override 130 public int compare(Person p1, Person p2) { 131 return p2.getAge() - p1.getAge(); 132 } 133 } 134 135 }
下面对这个程序进行说明。
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
转载于:http://www.cnblogs.com/skywang12345/p/3324788.html
个人总结:一般基本类型例如枚举类型,Date类型等已经继承了Comparable 接口,在使用的时候,可以直接使用对象的
compareTo方法进行比较。在自定义类中可以如果要定义某个属性的比较,继承Comparable 接口,实现compareTo方法。