Lambda可替代Comparator匿名类,推荐Comparator.comparing(Person::getAge);多条件用thenComparing;避免int减法溢出,应使用Integer.compare或comparingInt;字符串比较用compareTo或Objects.compare。

Comparator 匿名类太啰嗦,直接用 Lambda 替换
Java 8 起,Comparator 是函数式接口(只有一个抽象方法 compare()),天然适配 Lambda。原来写 5 行匿名类的地方,通常 1 行 Lambda 就能搞定。
常见错误是硬套语法却忽略泛型推导——比如没写类型就直接 (a, b) -> a.age - b.age,编译器可能报错“cannot infer type arguments”,这时得补全泛型或显式声明参数类型。
- 最简写法:
Comparator.comparing(person -> person.age)(推荐,语义清晰) - 手动写 compare 方法体:
(p1, p2) -> Integer.compare(p1.age, p2.age)(注意用Integer.compare避免整数溢出) - 需要多条件排序时链式调用:
comparing(Person::getName).thenComparing(Person::getAge)
为什么不能直接用减法 a - b 比较 int 字段
看似简洁的 (p1, p2) -> p1.score - p2.score 在极端值下会整数溢出:比如 p1.score = Integer.MAX_VALUE,p2.score = -1,结果为负数,逻辑反转。这不是 Lambda 的问题,而是比较逻辑本身有缺陷。
- 正确做法:统一用
Integer.compare(a, b)、Double.compare(a, b)等包装类静态方法 - 或者走
Comparator.comparingInt(Person::getScore),它内部已处理溢出 - 字符串等引用类型必须用
Objects.compare(a, b, String::compareTo)或直接a.compareTo(b),不能用==或减法
在 Arrays.sort() 和 Collection.sort() 中怎么传 Lambda
这两个方法都接受 Comparator super T>,Lambda 可直接作为实参,无需额外包装。
Arrays.sort(people, (p1, p2) -> p1.name.compareTo(p2.name));Collections.sort(list, Comparator.comparing(Person::getAge).reversed());- 注意:如果 list 元素为 null,
Person::getAge会 NPE;改用Comparator.comparing(Person::getAge, Comparator.nullsLast(Integer::compareTo))
什么时候 Lambda 反而更麻烦
不是所有场景都适合 Lambda。当比较逻辑复杂、需复用、或涉及多层 null 判断和转换时,硬塞进一行 Lambda 会让代码可读性暴跌,甚至难以调试。
- 例如:按城市拼音首字母分组再排序,涉及第三方库调用、异常捕获、空值 fallback —— 这时写个命名的私有方法 + 方法引用更稳妥
- Lambda 无法抛受检异常,若
compare()里要解析日期字符串并可能抛ParseException,就得用 try-catch 吞掉或转成运行时异常 - IDE 调试时,Lambda 行内断点不如独立方法直观;单元测试也难覆盖分支路径
真正该警惕的不是“用不用 Lambda”,而是把业务逻辑塞进一行表达式里还觉得酷。可读性和可维护性,永远比省那两行代码重要。

















