You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 15:43:38