Comparator.compare()必须返回负数、0或正数,严禁返回boolean/null/随机值;需防溢出、null异常、状态混用、链式短路误用、可变状态依赖。
Comparator.compare() 方法必须严格遵守三值契约
返回负数、0 或正数,分别代表“小于”“等于”“大于”。任何返回 boolean、null 或随机值的实现都会导致 Collections.sort() 抛出 IllegalArgumentException: Comparison method violates its general contract!。
常见错误包括:
- 用
a - b计算整数差(可能溢出,如Integer.MAX_VALUE - (-1)得负数) - 在比较字符串时直接用
==判空,未处理null值导致NullPointerException - 混用自然顺序和业务逻辑(比如先按状态排序再按时间,但状态枚举顺序与业务含义不一致)
lambda 表达式写 Comparator 要小心 null 安全
用 Comparator.comparing(Person::getName) 默认不允许 null;一旦列表中存在 name == null 的对象,运行时抛 NullPointerException。
安全写法需显式指定空值策略:
立即学习“Java免费学习笔记(深入)”;
Comparator.comparing(Person::getName, Comparator.nullsLast(String::compareTo))Comparator.comparing(Person::getAge, Comparator.nullsFirst(Integer::compareTo))- 若字段是基本类型包装类(如
Integer),注意Integer::compareTo本身可处理null,但前提是传入的Function不提前解包出null
链式比较器(thenComparing)的执行顺序不可逆
thenComparing 是“主序相等时才启用次序”,不是加权合并。比如: