comparator.compare()必须返回int(负数/0/正数),不可用true/false或==;需用integer.compare()、string.compareto()等避免溢出和空指针;多字段排序优先级高者先比;treeset/treemap中compare(a,b)==0必须与equals一致。

Comparator.compare() 方法必须返回 int,不能只写 true/false
很多人初学时直接在 compare() 里写 a.name.equals(b.name) 或 a.age > b.age,结果编译报错或排序乱序。Java 要求该方法严格返回负数(a 小于 b)、0(相等)、正数(a 大于 b)——这是排序算法依赖的三值语义。
正确做法是用减法(数值类型)或 Integer.compare()/String.compareTo() 等内置方法:
public int compare(Person a, Person b) {
// ✅ 安全:避免整数溢出
return Integer.compare(a.getAge(), b.getAge());
// ❌ 危险:age 是 int,a.age - b.age 可能溢出
// return a.getAge() - b.getAge();
}
- 对字符串、LocalDateTime 等不可减类型,必须用
.compareTo() - 对 double/float,用
Double.compare(a.val, b.val),别用==或减法 - 多个字段组合排序时,优先级高的字段先比,返回非零值就直接返回
使用 Lambda 表达式时,别漏掉参数类型推导的边界情况
写 Comparator.comparing(p -> p.getName()) 很简洁,但一旦字段是 null,运行时抛 NullPointerException。Java 8+ 提供了 Comparator.nullsFirst() 和 Comparator.nullsLast() 来兜底,但它们必须包裹在比较器内部,不是链式调用的末端。
常见错误写法:comparing(p -> p.getName()).nullsLast() —— 这会报错,因为 nullsLast() 返回的是新比较器,不能直接接在 comparing() 后当方法调用。
- ✅ 正确:用
comparing(…, nullsLast(String::compareTo)) - ✅ 或拆成两步:
Comparator.comparing(Person::getName, nullsLast(String::compareTo)) - ⚠️ 注意:如果 Person::getName 返回 String,而某些对象 name == null,不处理就会崩
Comparator.reversed() 不改变原比较器,且不能链式复用多次
reversed() 返回一个新比较器,原对象不变。有人误以为调用一次后后续所有排序都反向,其实不会;更危险的是连写 comp.reversed().reversed(),虽然语法合法,但每次都会新建对象,无谓开销。
- 需要反复切换方向时,建议提前定义两个常量:
ASC和DESC - 排序前才决定方向?直接用
list.sort(direction == ASC ? ASC_COMP : DESC_COMP),别现场调reversed() - Stream 排序中用
sorted(comp.reversed())没问题,但别在循环里反复调用它生成新实例
在 TreeSet/TreeMap 中传入 Comparator,必须保证“相等性”与 compare 结果一致
如果自定义 compare(a,b)==0,但 a.equals(b) 为 false,TreeSet 可能拒绝插入重复逻辑对象,TreeMap 可能覆盖 key——这不是 bug,是 Java 明确规定的契约:Comparator 定义的“相等”才是集合判断依据。
- 例如按姓名排序的
Person,若两人同名不同身份证号,compare()返回 0,TreeSet 就认为他们是同一个元素 - 解决办法:在
compare()中加入次级判据,比如Integer.compare(a.getId(), b.getId()),确保真正不同的对象不会返回 0 - 这个细节在 List.sort() 里不敏感,但在基于红黑树的集合里会直接暴露行为差异
实际项目里最常踩的坑不在语法,而在「以为 compare 返回布尔就是对的」和「忘了 null 和相等性契约」。这两个点不校验,上线后要么空指针,要么数据莫名消失。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











