如何用Optional流重构嵌套对象遍历代码以避免重复判空?
重构嵌套对象流式代码,消除重复非空判断
对象结构回顾
- Country:包含
name、State类型首府、List<State>类型州列表 - State:包含
name、City类型首府、List<City>类型城市列表 - City:仅包含
name
需求:获取所有名称为"XYZ"的State的首府名称列表,重构原有带多步非空判断的流式代码,消除重复空值校验。
方案1:用Java 8+ Optional 链式处理空值
把可能为空的节点用Optional包装,通过链式调用替代显式的非空判断:
List<String> xyzStateCapitals = Optional.ofNullable(country) .map(Country::getStateList) .orElse(Collections.emptyList()) .stream() .filter(state -> "XYZ".equals(state.getName())) .map(State::getCapital) .filter(Objects::nonNull) .map(City::getName) .filter(Objects::nonNull) .collect(Collectors.toList());
- 用
Optional.ofNullable(country)包装根对象,避免直接调用方法触发NPE - 调用
orElse(Collections.emptyList())确保集合不为null,后续stream可以正常执行 - 对State的首府(City)和City的名称,用
filter(Objects::nonNull)过滤空值,避免后续调用方法报错
方案2:给集合getter设置默认空集合(从根源减少空判断)
如果能修改实体类的getter方法,让可能为空的集合返回空集合而非null,就能省去集合的空值校验:
比如修改Country的getStateList方法:
public List<State> getStateList() { return stateList == null ? Collections.emptyList() : stateList; }
同理如果State的城市列表也可能为空,也可以做同样处理。之后代码简化为:
List<String> xyzStateCapitals = country.getStateList() .stream() .filter(state -> "XYZ".equals(state.getName())) .map(State::getCapital) .filter(Objects::nonNull) .map(City::getName) .filter(Objects::nonNull) .collect(Collectors.toList());
这样只需要处理单个对象(比如State的首府City)的空值,不用再管集合是否为null。
方案3:Null Object 模式(彻底消除空判断)
给City、State定义对应的空对象实现,让getter在原对象为null时返回空对象,而非null:
比如定义NullCity:
public class NullCity implements City { @Override public String getName() { return ""; // 可根据需求返回默认值,比如"未知首府" } }
然后修改State的getCapital方法:
public City getCapital() { return capital == null ? new NullCity() : capital; }
之后代码可以完全去掉空过滤(如果不需要空字符串的话,再加个过滤即可):
List<String> xyzStateCapitals = country.getStateList() .stream() .filter(state -> "XYZ".equals(state.getName())) .map(State::getCapital) .map(City::getName) .filter(name -> !name.isEmpty()) // 按需过滤空字符串 .collect(Collectors.toList());
内容的提问来源于stack exchange,提问作者Jayadeep
相关产品推荐
相关产品推荐

