一个类如果实现了Comparable
接口就表示该类是可比较的,可以用Collections.sort()
或Arrays.sort()
对该类的集合或数组进行排序:
public interface Comparable<T> {
public int compareTo(T o);
}
该接口只有一个方法,如果this.compareTo(o)
返回负值就表示this
比o
小,返回零则表示两个对象相等,否则表示this
比o
大。
下面是一个例子:
public class Film implements Comparable<Film> {
private int score;
public Film(int score) {
this.score = score;
}
@Override
public int compareTo(Film o) {
return this.score - o.score;
}
}
public static void main(String[] args) {
List<Film> films = new ArrayList<>();
films.add(new Film(65));
films.add(new Film(60));
films.add(new Film(80));
// 排序。
// [65,60,80]->[60,65,80],如果是数组是使用Arrays.sort()。
Collections.sort(films);
}
如果要从大到小排列,我们可以用Collections.reverse()
方法,但该方法只能用于集合,JDK没有在Arrays
类中实现与之对应的方法。
由于排序逻辑是写在类的内部,因此Comparable
也叫做内部比较器。
Comparable
有两个很明显的缺陷,代码必须写在类的内部,并且只能按照固定的规则进行排序。如果我们无法修改类的内部或者有多种排序规则,那么Comparable
接口就无能为力了,因此引入外部比较器Comparator
解决上述问题。
public interface Comparator<T> {
int compare(T o1, T o2);
boolean equals(Object obj);
// other methods
}
Comparator
接口中声明了两个方法,一个是compare()
,一个是equals()
,由于Object
类已经实现了equals()
方法,而它又是所有类的父类,因此我们无需实现equals()
方法,Comparator
重新声明equals()
方法仅仅是为了重写该方法的文档。compare()
方法和Comparable
的compareTo
非常类似,如果compare(o1,o2)
返回负值就表示o1
比o2
小,返回零则表示两个对象相等,否则表示o1
比o2
大。
我们用Comparator
接口改写上面的代码:
public static void main(String[] args) {
List<Film> films = new ArrayList<>();
films.add(new Film(65));
films.add(new Film(60));
films.add(new Film(80));
// 排序。
// [65,60,80]->[60,65,80]。
films.sort((o1, o2) -> o1.score - o2.score);
}