如何使用Java 8 Streams API替换三层嵌套for循环
用Java 8 Streams替换三层嵌套循环
先明确核心需求:通过Streams语法替换原三层嵌套循环,同时建议先优化数据结构提升查找效率(原循环存在重复遍历C列表的冗余操作)。
类定义(补充必要的getter/setter,原代码隐含这些方法)
class B { private Long id; private Long x; private String y; private Long z; // 省略getter、setter public Long getId() { return id; } public void setY(String y) { this.y = y; } public void setZ(Long z) { this.z = z; } } class A { private Long id; private List<B> bList; // 省略getter public Long getId() { return id; } public List<B> getBList() { return bList; } } class C { private Long id; private List<Long> bIds; private String y; private Long z; // 省略getter public Long getId() { return id; } public List<Long> getBIds() { return bIds; } public String getY() { return y; } public Long getZ() { return z; } }
高效版Streams实现(优化查找效率)
原三层循环时间复杂度为O(A数量 * 单A的B数量 * C数量),我们先预处理C列表成映射结构,把查找复杂度降到O(1),再用Streams遍历处理:
void f(List<A> aList, List<C> cList) { // 预处理C列表:构建「A/C的ID -> B的ID -> 对应C对象」的映射 Map<Long, Map<Long, C>> cLookupMap = cList.stream() .collect(Collectors.toMap( C::getId, c -> c.getBIds().stream() .collect(Collectors.toMap( bid -> bid, // 内层键是B的ID bid -> c // 内层值是对应的C对象 )) )); // 遍历A和B,通过映射快速找到匹配的C并赋值 aList.stream() .flatMap(a -> a.getBList().stream() // 把A的ID和B对象绑定成键值对,方便后续查找 .map(b -> new AbstractMap.SimpleEntry<>(a.getId(), b))) .forEach(entry -> { Long aId = entry.getKey(); B b = entry.getValue(); // 通过A的ID拿到对应C的B-ID映射表 Map<Long, C> bIdToC = cLookupMap.get(aId); if (bIdToC != null) { C matchedC = bIdToC.get(b.getId()); if (matchedC != null) { b.setY(matchedC.getY()); b.setZ(matchedC.getZ()); } } }); }
代码说明
- 预处理C列表:
- 外层Map用C的ID做键,把同ID的C(假设每个ID对应唯一C)聚合
- 内层Map把C的
bIds列表转换成键值对,直接通过B的ID定位到对应的C对象
- 遍历A和B:
- 用
flatMap把每个A的B列表展开,同时携带A的ID - 通过预构建的映射表快速查找匹配的C,找到后直接给B赋值
- 用
极简版Streams实现(完全对应原循环逻辑)
如果只是单纯用Streams语法替换循环,不做效率优化,写法如下(和原循环效率一致,仅语法不同):
void f(List<A> aList, List<C> cList) { aList.stream() .forEach(a -> a.getBList().stream() .forEach(b -> cList.stream() // 原循环的匹配条件 .filter(c -> a.getId().equals(c.getId()) && c.getBIds().contains(b.getId())) .forEach(c -> { b.setY(c.getY()); b.setZ(c.getZ()); }) ) ); }
内容的提问来源于stack exchange,提问作者Sandeep Barnabas
相关产品推荐
相关产品推荐

