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

如何更优雅地过滤嵌套对象列表中的指定General实例?

问题描述

我有一个GpbCodesAndVersions类型的列表,定义如下:

List<GpbCodesAndVersions> lst = Arrays.asList(
    new GpbCodesAndVersions("code1", 1, Arrays.asList(new General(1), new General(2))),
    new GpbCodesAndVersions("code2", 2, Arrays.asList(new General(1), new General(5))),
    new GpbCodesAndVersions("code3", 3, Arrays.asList(new General(2), new General(3))),
    new GpbCodesAndVersions("code4", 4, Arrays.asList(new General(2), new General(4)))
);

我需要对这个列表做过滤,最终得到仅包含General(status=1)元素的GpbCodesAndVersions列表,预期结果是:

GpbCodesAndVersions(code=code1, version=1, content=[General(status=1)]), GpbCodesAndVersions(code=code2, version=2, content=[General(status=1)])

我自己写的代码能实现需求,但想知道有没有更优雅的写法,我的代码如下:

List<GpbCodesAndVersions> versionOneGeneral = lst.stream().peek(x -> {
    List<General> generals = x.getContent().stream().filter(y -> y.getStatus().equals(1)).toList();
    x.setContent(generals);
}).filter(z -> !z.getContent().isEmpty()).toList();
优化方案

你的代码虽然能实现需求,但peek操作修改了原列表中的GpbCodesAndVersions对象,这不符合Stream API的设计初衷(peek主要用于调试,而非修改元素状态)。更优雅的写法应该是创建新的对象实例,避免对原数据产生副作用,同时让逻辑更清晰:

List<GpbCodesAndVersions> versionOneGeneral = lst.stream()
    // 先筛选出content中包含status=1的General的GpbCodesAndVersions
    .filter(gpb -> gpb.getContent().stream().anyMatch(gen -> gen.getStatus().equals(1)))
    // 为符合条件的对象创建新实例,仅保留status=1的General
    .map(gpb -> new GpbCodesAndVersions(
        gpb.getCode(),
        gpb.getVersion(),
        gpb.getContent().stream()
            .filter(gen -> gen.getStatus().equals(1))
            .toList()
    ))
    .toList();

优化点说明:

  • 提前用filter过滤掉不需要处理的对象,减少后续map操作的计算量
  • 通过map创建新对象,避免修改原列表元素,保持数据不可变性,更贴合函数式编程风格
  • 逻辑拆分明确,每一步操作的职责清晰,可读性更强

如果你的GpbCodesAndVersions类没有现成的对应构造函数,也可以添加复制构造函数简化对象创建:

// 在GpbCodesAndVersions类中添加复制构造函数
public GpbCodesAndVersions(GpbCodesAndVersions original, List<General> newContent) {
    this.code = original.getCode();
    this.version = original.getVersion();
    this.content = newContent;
}

// 对应的Stream写法
List<GpbCodesAndVersions> versionOneGeneral = lst.stream()
    .filter(gpb -> gpb.getContent().stream().anyMatch(gen -> gen.getStatus().equals(1)))
    .map(gpb -> {
        List<General> filteredContent = gpb.getContent().stream()
            .filter(gen -> gen.getStatus().equals(1))
            .toList();
        return new GpbCodesAndVersions(gpb, filteredContent);
    })
    .toList();

内容的提问来源于stack exchange,提问作者HudsonHornet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:01:39