✅ 一句话区分
Comparable
:一个类 自己具备"可比较性"------实现compareTo
方法,表示默认排序方式。Comparator
:外部定义 比较逻辑------实现compare
方法,用来指定多个排序规则(或临时排序规则)。
一、Comparable
:自然排序,类内定义
特点
- 属于 "类自身"定义排序规则。
- 实现
Comparable<T>
接口,需要重写compareTo()
方法。 - 只能有一个排序规则(因为在类里写死了)。
示例:定义一个 Student
类,按年龄升序排序
csharp
import java.util.*;
public class Student implements Comparable<Student> {
// 学生姓名
private String name;
// 学生年龄
private int age;
// 构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 获取姓名
public String getName() {
return name;
}
// 获取年龄
public int getAge() {
return age;
}
// 重写 Comparable 接口的 compareTo 方法
@Override
public int compareTo(Student other) {
// 按年龄升序排列
return this.age - other.age;
}
// 重写 toString 方便打印
@Override
public String toString() {
return name + " (" + age + ")";
}
// 测试代码
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("Alice", 23));
list.add(new Student("Bob", 20));
list.add(new Student("Charlie", 22));
// 按照 compareTo 排序
Collections.sort(list);
// 打印结果
System.out.println("按年龄升序(Comparable):");
for (Student s : list) {
System.out.println(s);
}
}
}
输出
scss
按年龄升序(Comparable):
Bob (20)
Charlie (22)
Alice (23)
Collections.sort(List) 使用说明
Collections.sort支持两种传参: 1, 直接传入集合对象; 2, 传入集合对象和 Comparator 实现;
当调用 Collections.sort(list), 底层会判断你传入的 list
中元素是否实现了 Comparable
接口:
- 如果实现了,就自动使用每个元素的
compareTo()
方法进行比较排序; - 如果没有实现,会抛出异常(
ClassCastException
); - 如果你调用的是
Collections.sort(list, comparator)
,就会使用你传入的Comparator
的compare()
方法,而不是compareTo()
。
二、Comparator
:定制排序,类外定义
特点
- 可以不修改类本身,就能排序。
- 更灵活:可以定义多个排序逻辑。
- 实现
Comparator<T>
接口,重写compare(T o1, T o2)
方法。
示例
使用 Comparator
实现不同排序逻辑
csharp
import java.util.*;
public class StudentComparatorDemo {
public static class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return name + " (" + age + ")";
}
}
// 定义按姓名升序排序的比较器
public static class NameComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// 按名字字母升序排列
return s1.getName().compareTo(s2.getName());
}
}
// 定义按年龄降序排序的比较器
public static class AgeDescComparator implements Comparator<Student> {
@Override
public int compare(Student s1, Student s2) {
// 年龄从大到小
return s2.getAge() - s1.getAge();
}
}
public static void main(String[] args) {
List<Student> list = new ArrayList<>();
list.add(new Student("Alice", 23));
list.add(new Student("Bob", 20));
list.add(new Student("Charlie", 22));
// 按姓名升序排序
Collections.sort(list, new NameComparator());
System.out.println("按姓名升序(Comparator):");
for (Student s : list) {
System.out.println(s);
}
// 按年龄降序排序
Collections.sort(list, new AgeDescComparator());
System.out.println("按年龄降序(Comparator):");
for (Student s : list) {
System.out.println(s);
}
}
}
三、Comparable
和 Comparator
总结对比表格
特性 | Comparable | Comparator |
---|---|---|
所在位置 | 类内部实现(implements ) |
类外定义(独立类或匿名类或 Lambda) |
方法名 | compareTo(T o) |
compare(T o1, T o2) |
是否可定义多个规则 | 否,只能有一个实现 | 是,可以有多个 Comparator 实现 |
是否破坏原类封装 | 是,需要修改类代码 | 否,不需要修改类代码 |
使用场景 | 类默认排序方式 | 临时排序、多个排序条件 |
推荐方式 | 只需要一种排序时使用 | 推荐使用,灵活、解耦 |
四、使用 Lambda 表达式简化 Comparator(Java 8+)
less
Collections.sort(list, (s1, s2) -> s1.getName().compareTo(s2.getName()));
或者使用 List.sort()
方法:
less
list.sort(Comparator.comparing(Student::getName));
五、结论:如何选用?
- 需要类本身支持排序(默认排序) ➜ 实现
Comparable
- 外部控制排序逻辑(灵活多样) ➜ 使用
Comparator