Java里如何对List进行自定义排序_JavaComparator使用说明

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。不能依赖“看起来没报错”就认为安全。

  • 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(),依然会崩。这个细节在联调阶段才暴露,但根源在第一层比较器没兜底。