如何用Java 8 Streams API替换嵌套三重循环赋值逻辑
如何用Java 8 Streams API替代嵌套三重循环为对象属性赋值
我现在要处理三个列表,通过嵌套三重循环根据匹配条件给对象属性赋值。作为Java新手,想知道怎么用Java 8 Streams API替换下面的嵌套循环逻辑,求指导。
类定义
class B { Long id; Long x; String y; Long z; // 假设已生成getter和setter方法 } class A { private Long id; private List<B> bList; // 假设已生成getter方法 } class C { private Long id; private List<Long> bIds; private String y; private Long z; // 假设已生成getter方法 }
待替换的嵌套三重循环
void f(List<A> aList, List<C> cList) { for(A a : aList) { List<B> bList= a.getBList(); for(B b : bList) { for(C c : cList) { if(a.getId().equals(c.getId()) && c.getBIds().contains(b.getId())) { b.setZ(c.getZ()); b.setY(c.getY()); } } } } }
用Streams API实现的方案
第一步:预处理C列表,构建高效查找映射
原循环中c.getBIds().contains(b.getId())是线性查找,效率较低。先把cList转换成嵌套Map,外层key为A/C的id,内层key为B的id,后续查找可达到O(1)时间复杂度:
Map<Long, Map<Long, C>> cMapping = cList.stream() .collect(Collectors.toMap( C::getId, c -> c.getBIds().stream() .collect(Collectors.toMap( bid -> bid, bid -> c )) ));
第二步:用Streams遍历赋值
通过flatMap展开所有B对象,再通过预处理的映射找到匹配的C,完成属性赋值:
void fWithStreams(List<A> aList, List<C> cList) { // 构建查找映射 Map<Long, Map<Long, C>> cMapping = cList.stream() .collect(Collectors.toMap( C::getId, c -> c.getBIds().stream() .collect(Collectors.toMap( bid -> bid, bid -> c )) )); // 遍历并赋值 aList.stream() .flatMap(a -> a.getBList().stream() .peek(b -> { Map<Long, C> bIdToC = cMapping.get(a.getId()); if (bIdToC != null) { C matchedC = bIdToC.get(b.getId()); if (matchedC != null) { b.setY(matchedC.getY()); b.setZ(matchedC.getZ()); } } }) ) .forEach(b -> {}); // 终端操作触发流执行,也可用count()替代 }
逻辑说明
- 预处理映射大幅降低了原循环的时间复杂度,避免重复遍历查找
flatMap将每个A的bList展开为单个B的流,统一处理peek用于在流处理过程中修改B的属性,需配合终端操作(如forEach)触发执行- 该实现和原嵌套循环的逻辑完全一致:若一个B匹配多个C,最后匹配的C会覆盖属性值
内容的提问来源于stack exchange,提问作者Sandeep Barnabas
相关产品推荐
相关产品推荐

