Comparator 为何要重写
在 Java 中,Comparator 是一个函数式接口,用于定义对象之间的比较规则。
之所以要“重写”(更准确说是实现其抽象方法),核心原因是:
Java 不知道你希望按什么规则比较两个对象,必须由你指定。
下面从几个角度解释。
一、Comparator 的本质
Comparator 接口中最重要的一个方法是:
int compare(T o1, T o2);
Java 本身无法自动判断:
- 按年龄比?
- 按姓名比?
- 按价格、时间、优先级?
所以你必须重写(实现)这个方法,告诉 Java 比较逻辑。
二、为什么不能“不重写”
1️⃣ Java 是强类型、无默认比较规则的
例如:
class Person {
String name;
int age;
}
Java 并不知道:
age小的是“小”- 还是
name字典序小的是“小”
因此:
Collections.sort(list); // ❌ 编译错误
必须提供比较规则。
三、重写 Comparator 的常见方式
✅ 方式一:匿名内部类(传统写法)
Comparator comparator = new Comparator() {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
};
✅ 方式二:Lambda(推荐)
Comparator comparator = (p1, p2) -> p1.getAge() - p2.getAge();
✅ 方式三:方法引用(更简洁)
Comparator comparator = Comparator.comparingInt(Person::getAge);
四、Comparator vs Comparable
| 对比项 | Comparator | Comparable |
|---|---|---|
| 所在位置 | 外部比较器 | 对象自身实现 |
| 方法 | compare(o1, o2) |
compareTo(o) |
| 是否必须重写 | ✅ 必须 | ✅ 必须 |
| 灵活性 | 高(可多种排序规则) | 低(只能一种自然顺序) |
| 典型用途 | 排序策略 | 定义“自然顺序” |
五、为什么有时“看起来没重写”?
例如:
list.sort(Comparator.comparing(Person::getName));
其实:
Comparator.comparing(...)内部已经帮你重写了compare- 你只是“声明规则”,而不是手写
compare
六、总结一句话
Comparator需要重写,是因为比较规则是业务相关的,Java 无法自动推断,必须由开发者定义。
如果你愿意,我也可以:
- 用 源码角度解释
Comparator - 或结合 排序、TreeSet、Stream 排序 给你实战示例