如何用Java 8 Stream实现嵌套类结构中属性的求和计算?
使用Java 8 Stream实现多层集合的求和逻辑
这题我太熟了!Java 8的Stream API刚好能把你这种嵌套循环的求和逻辑变得更简洁、更具可读性,完全不用嵌套for循环。我给你分两种场景来实现:
场景1:简洁优先,分开计算两个总和
这种写法最直观,代码清晰易懂,数据量不大的话完全够用:
A aInstance = new A(); // 计算所有C的a属性之和sum_a int sum_a = aInstance.getBList().stream() // 把每个B中的C集合扁平化为单个C元素的流(相当于把嵌套的List<C>拆成一维流) .flatMap(b -> b.getCList().stream()) // 提取每个C的a属性,转成IntStream(专门处理int类型的流,效率更高) .mapToInt(C::getA) // 对流中的int值求和 .sum(); // 计算所有C的b+c属性之和sum_b_c int sum_b_c = aInstance.getBList().stream() .flatMap(b -> b.getCList().stream()) // 对每个C计算b+c的值,转成IntStream .mapToInt(c -> c.getB() + c.getC()) .sum();
场景2:性能优先,一次性计算两个总和
如果你的集合数据量很大,不想遍历两次集合(毕竟两次遍历会多消耗一倍的时间),可以用一次遍历同时累加两个值的方式,这里给你两种实现思路:
思路1:用原子类(AtomicInteger)累加
AtomicInteger sumA = new AtomicInteger(0); AtomicInteger sumBC = new AtomicInteger(0); aInstance.getBList().stream() .flatMap(b -> b.getCList().stream()) // 遍历每个C元素,同时更新两个原子类的值 .forEach(c -> { sumA.addAndGet(c.getA()); sumBC.addAndGet(c.getB() + c.getC()); }); // 最终结果 int sum_a = sumA.get(); int sum_b_c = sumBC.get();
思路2:自定义收集器(更符合Stream的函数式风格)
先定义一个用来保存求和结果的类:
class SumResult { int sumA; int sumBC; // 累加单个C元素的逻辑 SumResult accumulate(C c) { sumA += c.getA(); sumBC += c.getB() + c.getC(); return this; } // 合并两个SumResult(并行流场景下会用到) SumResult combine(SumResult other) { sumA += other.sumA; sumBC += other.sumBC; return this; } }
然后用Stream的collect方法一次性收集结果:
SumResult result = aInstance.getBList().stream() .flatMap(b -> b.getCList().stream()) .collect(SumResult::new, SumResult::accumulate, SumResult::combine); int sum_a = result.sumA; int sum_b_c = result.sumBC;
关键知识点说明
flatMap:是实现多层集合扁平化的核心,它能把Stream<List<C>>转换成Stream<C>,相当于把嵌套的集合“拍平”成一维流。mapToInt:相比普通的map,它直接生成IntStream,避免了自动装箱/拆箱的性能开销,更适合处理int类型的求和操作。- 如果是并行流场景,自定义收集器的
combine方法一定要正确实现,保证结果的正确性;原子类本身是线程安全的,并行流下也能正常工作。
内容的提问来源于stack exchange,提问作者run_time_error
相关产品推荐
相关产品推荐

