Java中用Comparator接口自定义List排序,需传入Comparator实例给sort()方法,推荐lambda表达式;注意null处理、多字段链式排序及避免溢出与字符串误用。

用Comparator接口实现List自定义排序
Java中对List自定义排序,核心是传入一个Comparator实例给Collections.sort()或List.sort()。这个接口只定义了一个compare(T o1, T o2)方法,返回负数、0、正数分别表示“小于”“等于”“大于”。别写错方法签名——它不是compareTo(那是Comparable的),也不接受泛型通配符乱写,比如Comparator>会导致编译失败。
lambda表达式是最简洁的写法
JDK 8+ 推荐直接用lambda,省去匿名内部类的模板代码。注意参数类型通常可由编译器推导,但遇到泛型擦除场景(如List)时可能需要显式声明。
list.sort((a, b) -> a.getAge() - b.getAge()); // 升序 list.sort((a, b) -> b.getName().compareTo(a.getName())); // 降序
常见错误:用==比较字符串,或在减法中造成整数溢出(比如用int字段相减)。应优先用Integer.compare(a, b)或String.compareTo()这类安全方法。
处理null值必须主动判断
Comparator默认不处理null,一旦列表含null元素,运行时抛NullPointerException。不能依赖“看起来没报错”就认为安全。
立即学习“Java免费学习笔记(深入)”;
- 用
Comparator.nullsFirst()或Comparator.nullsLast()包装已有比较器 - 在lambda里手动判空,例如
(a, b) -> { if (a == null && b == null) return 0; if (a == null) return -1; if (b == null) return 1; return a.getValue().compareTo(b.getValue()); } - 避免用
Objects.compare()直接套用——它对null参数仍会调用成员方法,不解决根本问题
多字段排序要用thenComparing链式调用
不要手写嵌套三元运算或if逻辑。用thenComparing()组合多个条件,清晰且高效:
list.sort(Comparator.comparing(Person::getDepartment)
.thenComparing(Person::getSalary)
.thenComparing(Person::getName));每个thenComparing可单独指定升/降序,比如.thenComparing(Comparator.reverseOrder());也可传入另一个Comparator实例。注意链式调用顺序就是优先级顺序——部门相同才比薪资,薪资也相同才比姓名。
真正容易被忽略的是:如果某个字段是基本类型包装类(如Integer),而列表中存在null,即使用了thenComparing,只要没配合nullsFirst()/nullsLast(),依然会崩。这个细节在联调阶段才暴露,但根源在第一层比较器没兜底。










