java中optional与stream配合过滤空值的关键是用flatmap+optional::stream(jdk9+)或stream.ofnullable(jdk8+),而非map;map仅转换不过滤,flatmap通过展开语义自动跳过null/empty。

处理单个 Optional 对象并融入流中
比如查用户后要和其他数据一起 map 或 collect:
- JDK 9+:直接用 opt.stream() —— 空 Optional 返回空流,后续操作自动跳过
- JDK 8:用 opt.flatMap(s -> Stream.ofNullable(s)),比 isPresent + get + of 更函数式
- 别写 opt.map(Stream::of) —— 得到的是
Optional<stream>></stream>,无法继续 filter 或 collect
处理 List> 批量结果
常见于批量查询(如多个 ID 查用户),返回的是 List<optional>></optional>:
- 传统写法:
.filter(Optional::isPresent).map(Optional::get)—— 冗余且易出错 - 推荐写法:
.flatMap(Optional::stream)(JDK 9+)或.flatMap(opt -> Stream.ofNullable(opt.orElse(null)))(JDK 8) - 效果一样:空值自动被忽略,流中只剩非空值,无需显式判空
嵌套 Optional 字段提取(如 user.getAddress().getZipCode)
链式调用容易产生 Optional<optional>></optional>:
- 先用 flatMap 展开外层:
.map(u -> u.getAddress().map(Address::getZipCode))→ 得到Optional<optional>></optional> - 再用两次 flatMap(Optional::stream):
.flatMap(Optional::stream).flatMap(Optional::stream) - 等价于一次展开外层、一次展开内层,并自动过滤所有 empty
源头就避免 null:用 Stream.ofNullable 替代 filter(Objects::nonNull)
当原始集合可能含 null(如解析 JSON、调第三方接口),别用 .filter(Objects::nonNull):
- 它把 null 当“脏数据”删掉,掩盖了业务上 null 是“合法缺失”的事实
- 改用:
list.stream().flatMap(s -> Stream.ofNullable(s)) - 额外好处:如果
list本身为 null,Stream.ofNullable(list).flatMap(Collection::stream)也能兜底
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











