我们先来看这两个接口的定义:
//Comparable
package java.lang;
import java.util.*;
/**
This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.Lists (and arrays) of objects that implement this interface can be sorted automatically by {@link Collections#sort(List) Collections.sort} (and {@link Arrays#sort(Object[]) Arrays.sort}).
*/
public interface Comparable<T> {
public int compareTo(T o);
}
//Comparator
package java.util;
/**
A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as {@link Collections#sort(List,Comparator) Collections.sort} or {@link Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control over the sort order.
*/
public interface Comparator {
int compare(T o1, T o2);
boolean equals(Object obj);
}
这里顺便摘了一些注释过来,可以从注释的描述上看到两个接口的作用差不多,都是用作比较或排序,并且都可以用于Collections.sort和Arrays.sort。
当然它们也有一些区别:
下面用具体的代码来看一下。
我们写一个简单的Person类,包含姓名和年龄。想要按照年龄大小排序。
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
现在来实现Comparable接口,注意如果要实现从小到大排序的话,需要保证自身比传入对象小的时候返回负数,相等的时候返回0,比传入对象大的时候返回整数。如果弄反的话会变成从大到小排序。
public class Person implements Comparable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Person p) {
return this.age - p.getAge();
}
public static void main(String[] args) {
Person[] people = new Person[]{new Person("xiaoming", 20), new Person("xiaohong", 15), new Person("xiaowei", 10)};
System.out.println("\n排序前");
for (Person person : people) {
System.out.print(person.getName() + ":" + person.getAge());
}
Arrays.sort(people);
System.out.println("排序后");
for (Person person : people) {
System.out.print(person.getName() + ":" + person.getAge());
}
}
}
接下来试试Comparator,我们需要写一个类实现这个接口。同样是需要注意如果要实现从小到大排序,需要保证o1比o2小的时候返回负数。
public class PersonComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public static void main(String[] args) {
Person[] people = new Person[]{new Person("xiaoming", 20), new Person("xiaohong", 15), new Person("xiaowei", 10)};
System.out.println("排序前");
for (Person person : people) {
System.out.print(person.getName() + ":" + person.getAge());
}
Arrays.sort(people, new PersonComparator());
System.out.println("\n排序后");
for (Person person : people) {
System.out.print(person.getName() + ":" + person.getAge());
}
}
}
可以看到调用Arrays.sort的时候额外传入了我们自定义的比较器。
那什么时候该用Comparable什么时候该用Comparator呢?个人认为并没有什么差别。如果想实现类的自比较或调用Arrays.sort等方法时或希望传入SortedMap等有序结构时可以自动排序的时候,可以在类中实现Comparable接口;当无法修改一个类的代码或类自身已经实现了Comparable接口的时候,我们可以选择实现一个Comparator比较器从外部去比较,比如对于Integer类,我们如果想按照绝对值大小排序的话,就可以实现一个Comparator。