这两个类都是接口,首先看看里面的源码:
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}
package java.util;
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
}
上面分别是comparable和comparator的源码,两个都是接口,并且非常简单,仅仅有一两个方法。
下面看用法:
Comparable用法:
import java.util.Arrays;
public class ComparableUser implements Comparable {
private String id;
private int age;
public ComparableUser(String id, int age) {
this.id = id;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int compareTo(Object o) {
return this.age - ((ComparableUser) o).getAge();
}
/**
* 测试方法
*/
public static void main(String[] args) {
ComparableUser[] users = new ComparableUser[] {
new ComparableUser("u1001", 25),
new ComparableUser("u1002", 20),
new ComparableUser("u1003", 21) };
Arrays.sort(users);
for (int i = 0; i < users.length; i++) {
ComparableUser user = users[i];
System.out.println(user.getId() + " " + user.getAge());
}
}
}
comparator用法:
public class User {
private String id;
private int age;
public User(String id, int age) {
this.id = id;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
import java.util.Arrays;
import java.util.Comparator;
public class UserComparator implements Comparator {
public int compare(Object arg0, Object arg1) {
return ((User) arg0).getAge() - ((User) arg1).getAge();
}
public static void main(String[] args) {
User[] users = new User[] { new User("u1001", 25),
new User("u1002", 20), new User("u1003", 21) };
Arrays.sort(users, new UserComparator());
for (int i = 0; i < users.length; i++) {
User user = users[i];
System.out.println(user.getId() + " " + user.getAge());
}
}
}
上面分别就是comparable和comparator两个接口的用法。
理论部分:
Comparable & Comparator 都是用来实现集合中元素的比较、排序的,只是 Comparable 是在集合内部定义的方法实现的排序,Comparator 是在类外部实现的排序,所以,如想实现排序,就需要在类外定义 Comparator 接口的方法或在类内实现 Comparable 接口的方法。(这里所说的类外,是值User类的类外。从上面的代码可以很明显的看出来,ComparableUser 类实现了comparable接口,comparable接口就是类内部实现,改变了类的结构。User类不实现比较功能,不能够比较,但是通过类外定义比较器UserComparator 使其具备可比较功能。)
Comparator位于包java.util下,而Comparable位于包 java.lang下
Comparable 是一个对象本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)
自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序,这里的自然顺序就是实现Comparable接口设定的排序方式。
而 Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。
因此,可以说上面的两个接口,一个是自己完成比较,一个是类外部定义比较器实现比较的差别而已。
用 Comparator 是策略模式(strategy design pattern),就是不改变对象自身,而用一个策略对象(strategy object)来改变它的行为。
这句话,我觉得说得很好!因为Comparator 是比较器,并且是在类外定义的,可以多个类复用!相当于是一种策略,当然可以定义多个策略。如果是在类内部定义的比较功能,那类就不具备这种策略了。
有时在实现Comparator接口时,并没有实现equals方法,可程序并没有报错,原因是实现该接口的类也是Object类的子类,而Object类已经实现了equals方法。
这一点也是需要注意的。按理论上讲,当comparator的compare(T,T)方法返回0的时候,equals方法应当返回true表示两个对象相等。
上面的ComparableUser 类实现了comparable接口,所以有下面的事实:
Comparable接口只提供了 int compareTo(T o)方法,也就是说假如我定义了一个Person类,这个类实现了 Comparable接口,那么当我实例化Person类的person1后,我想比较person1和一个现有的Person对象person2的大小时,我就可以这样来调用:person1.comparTo(person2),通过返回值就可以判断了;
而此时如果你定义了一个 PersonComparator(实现了Comparator接口)的话,那你就可以这样:
PersonComparator comparator= new PersonComparator();
comparator.compare(person1,person2);。
通过比较我们可以发现,两个接口使用情况不同:
1、两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码
2、用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
3、Comparator可以看成一种算法的实现,将算法和数据分离,Comparator也可以在下面两种环境下使用:
3.1 类的设计师没有考虑到比较问题而没有实现Comparable,可以通过Comparator来实现排序而不必改变对象本身
3.2 可以使用多种排序标准,比如升序、降序等。
参考:
http://pengcqu.iteye.com/blog/490149
http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt159
http://blog.csdn.net/mageshuai/article/details/3849143