如何在Stream执行collect操作前过滤null元素避免空指针异常
问题根因
原代码抛出NullPointerException的核心逻辑是:map阶段的返回值是VersionNumber实例或null,但后续flatMap(Optional::stream)要求入参必须是Optional类型,null值调用stream()方法会直接触发空指针——并非只有全量元素返回null时才会抛异常,只要存在任意一个map返回null的场景都会触发报错。
可行修复方案
以下方案均可自动过滤null值,无空指针风险,无匹配元素时默认返回空列表:
方案1:最小改动适配原有flatMap逻辑(Java 9+支持)
调整map阶段的返回值为Optional类型,匹配成功时用Optional.of()包装实例,匹配失败返回Optional.empty(),后续flatMap(Optional::stream)会自动过滤空值,逻辑和原本的设计一致:versions.stream() .map(vs -> { if(vs.matches("^matched string$")) { // 原有业务逻辑 return Optional.of(new VersionNumber(tmp[0], tmp[1], tmp[2])); } return Optional.empty(); }) .flatMap(Optional::stream) .collect(Collectors.toList());方案2:直接过滤null值(Java 8+兼容,最简洁)
不需要修改map内的业务逻辑,在map操作后追加非空过滤即可,没有额外的对象包装开销,可读性更强:versions.stream() .map(vs->{ if(vs.matches("^matched string$")) { // 原有业务逻辑 return new VersionNumber(tmp[0], tmp[1], tmp[2]); } return null; }) .filter(Objects::nonNull) .collect(Collectors.toList());方案3:无匹配时返回null的适配
如果业务要求无任何匹配项时返回null而非空列表,只需要在收集结果后加一层空判断即可:List<VersionNumber> collectResult = versions.stream() .map(vs->{ if(vs.matches("^matched string$")) { // 原有业务逻辑 return new VersionNumber(tmp[0], tmp[1], tmp[2]); } return null; }) .filter(Objects::nonNull) .collect(Collectors.toList()); return collectResult.isEmpty() ? null : collectResult;常规业务场景下更推荐返回空列表而非null,可以减少下游遍历结果时的空判断逻辑,降低额外的空指针风险。
内容的提问来源于stack exchange,提问作者user504909
相关产品推荐
相关产品推荐

