Comparator用于定义Java自定义排序逻辑,返回负数/0/正数表示大小关系,需处理空值、多条件组合及中文拼音排序等场景。
用 Comparator 实现自定义排序逻辑
Java 集合本身不带条件排序能力,得靠 Comparator 接口描述“怎么比”。它只关心两个元素谁在前、谁在后,返回负数、0 或正数即可。别写成布尔返回值——那是 Predicate 的事。
常见错误是直接在 sort() 里传一个 lambda 却忽略泛型,比如对 List 写成 (a, b) -> a.length() - b.length() 没问题,但若类型擦除后比较对象字段,编译器可能报错或运行时 ClassCastException。
- 优先用方法引用:比如按字符串长度排,写
Comparator.comparing(String::length)比手写 lambda 更安全 - 多个条件叠加用
thenComparing():如先按年龄升序,年龄相同时按姓名降序,写成comparing(Person::getAge).thenComparing(Person::getName, Comparator.reverseOrder()) - 空值要显式处理:默认
null会抛NullPointerException,用Comparator.nullsFirst()或nullsLast()包一层
Collection.sort() 和 Stream.sorted() 怎么选
核心区别就一条:前者直接改原集合(要求集合可修改),后者返回新流、不碰原数据。如果你排序后还要继续用原列表做其他操作,别用 sort() 把它改乱了。
性能上没本质差异,但 Stream.sorted() 在并行流里能自动分段归并,适合大数据量且已有 parallelStream() 上下文的场景;而 Collection.sort() 底层调的是 Timsort,对小数据更轻量。
立即学习“Java免费学习笔记(深入)”;
- 原地排序且确定集合可变 → 用
Collections.sort(list, comparator) - 不想动原数据,或后续还要 filter/map → 用
list.stream().sorted(comparator).collect(Collectors.toList()) - 排序后只取前 N 条?别先 collect 再 subList,直接
stream().sorted().limit(N).collect()更省内存
实体类字段为空时排序崩溃怎么办
最常见的运行时异常是 java.lang.NullPointerException,发生在比较字段为 null 时调用了 .compareTo() 或 .length() 这类方法。这不是排序逻辑写错了,而是没预设空值策略。