Java——Comparable接口和Comparator接口的区别
Comparable
接口
Comparable
是一个排序接口。若一个类实现了Comparable
接口,即代表该类实现了compareTo
方法,该方法规定了该类的对象的比较规则(两个对象如何比较“大小”)。
类通过实现o1.compareTo(o2)
方法来比较o1
和o2
的大小:
- 若返回正数,意味着
o1
大于o2
; - 若返回负数,意味着
o1
小于o2
; - 若返回零,则意味着
o1
等于o2
。
Comparator
接口
Comparator
是比较器接口。若我们只需要控制某些对象的次序,而类本身并不支持排序(即没有实现Comparable
接口),对于这种情况,我们可以通过建立一个比较器(即关于该类的一个Comparator
接口实现类)来进行排序。
比较器需实现方法compare(T o1, T o2)
,其原理与上面的o1.compareTo(o2)
方法类似,这里就不再描述。
两者的联系
Comparable
接口实现在自身类中,代表默认排序,相当于内部比较器;而Comparator
接口则是为类外实现的一个比较器,相当于外部比较器。
案例加深理解
用于比较的自定义Student
类:
1 | public class Student implements Comparable<Student> { |
上述Student
类实现了Comparable
接口,带有默认排序,调试代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14public class Main {
public static void main(String[] args) {
List<Student> arr = new ArrayList<>();
arr.add(new Student("John", 100));
arr.add(new Student("Bob", 75));
arr.add(new Student("Alice", 100));
arr.add(new Student("Jake", 90));
System.out.println(arr);
System.out.println("------------------------");
Collections.sort(arr); //默认排序
System.out.println(arr);
}
}
另外定义一个实现Compartor
接口的比较器如下:
1 | public class StuCompartor implements Comparator<Student> { |
调试代码:
1 | public class StuMain { |
运行结果均如下所示:
1 | [Student{name='John', grade=100}, Student{name='Bob', grade=75}, Student{name='Alice', grade=100}, Student{name='Jake', grade=90}] |
扩展
若只排序一次,则可不额外定义比较器,直接利用匿名内部类即可:1
2
3
4
5
6Collections.sort(arr, new Comparator<Student>() {
public int compare(Student o1, Student o2) {
return o1.getGrade() > o2.getGrade() ? 1 : o1.getGrade() < o2.getGrade() ? -1 : o1.getName().compareTo(o2.getName());
}
});
很明显上述写法仍然让人觉得繁琐、复杂,进一步可利用Lambda表达式进行化简:
1 | Collections.sort(arr, (Student o1, Student o2) -> { |
再进行一些化简(去掉参数类型):
1 | Collections.sort(arr, (o1, o2) -> { |
最终利用方法应用进行化简(同时定义了首选比较量相等时的继续比较依据):
1 | Collections.sort(arr, comparing(Student::getGrade) |
若需要逆序:
1 | Collections.sort(arr, comparing(Student::getGrade) |