java stream排序遇null会抛nullpointerexception,应使用nullsfirst/nullslast包装比较器、提前filter过滤或自定义比较器处理;sorted为中间操作,须接collect等终端操作才生效。

Java Stream 排序时遇到 null 元素会抛出 NullPointerException,因为默认的比较器(如 Comparator.naturalOrder())不支持 null。解决的关键是使用能安全处理 null 的比较器,或提前过滤/映射 null。
用 nullsFirst / nullsLast 包装比较器
这是最常用、最推荐的方式。Java 8+ 提供了 Comparator.nullsFirst() 和 Comparator.nullsLast(),可将 null 统一排在前面或后面,内部已做空值防护。
-
Comparator.nullsFirst(Comparator.naturalOrder()):null 排最前,其余按自然顺序 -
Comparator.nullsLast(Comparator.naturalOrder()):null 排最后,其余按自然顺序 - 对自定义对象,可用
Comparator.comparing(Person::getName, Comparator.nullsLast(String::compareTo))
对字段提取前做非空映射
如果只想排序非 null 值,且不希望 null 出现在结果中,可在排序前用 filter(Objects::nonNull) 或对排序字段做安全提取:
stream.filter(Objects::nonNull).sorted(Comparator.naturalOrder())- 对对象字段:用
comparing(p -> p.getName(), nullsLast(String::compareTo)),比先 filter 更灵活(保留原元素)
自定义比较器显式处理 null
适用于复杂逻辑,比如想让 null 视为最小值、最大值,或按特定业务规则排序:
- 返回负数表示 a 在 b 前,正数表示 a 在 b 后,0 表示相等
- 示例:
(a, b) -> { if (a == null && b == null) return 0; if (a == null) return -1; if (b == null) return 1; return a.compareTo(b); } - 建议封装成静态方法复用,避免重复写判断逻辑
注意 sorted() 是中间操作,需终端操作触发
sorted() 本身不执行,必须接 collect()、forEach() 等终端操作才会运行。若链式调用中漏掉终端操作,空指针不会立即出现,但一旦触发就会暴露问题。
- 错误写法:
list.stream().sorted(nullsLast(naturalOrder()))(没收集,无效果) - 正确写法:
list.stream().sorted(nullsLast(naturalOrder())).collect(Collectors.toList())
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











