使用Java 8流迭代两个列表

时间:2015-05-20 22:05:24

标签: lambda java-8 java-stream

如何在Java 8流中编写以下内容?

int total = 0;
  for (ObjectA obja : rootObj.getListA()) {
    for (ObjectB objb : obja.getListB()) {
        total += objb.getCount() * obja.getCount();
    }
   }

return total;

4 个答案:

答案 0 :(得分:4)

将嵌套for循环转换为Stream API使用的规范解决方案是flatMap

return rootObj.getListA().stream()
.flatMapToInt(objA->objA.getListB().stream()
                                   .mapToInt(objB->objB.getCount() * objA.getCount()))
.sum();

这允许您为每个内部迭代执行操作。但是,在汇总的特殊情况下,您可以简化操作,因为无论您计算(a+b+c+d)还是(a+b)+(c+d)都无关紧要:

return rootObj.getListA().stream()
.mapToInt(objA->objA.getListB().stream()
                               .mapToInt(objB->objB.getCount() * objA.getCount()).sum())
.sum();

当我们记住基本的算术时,我们也应该记得(a*x)+(b*x)等于(a+b)*x,换句话说,没有必要将ListB的每个项目与计数为objA,因为我们也可以将该结果的总和加倍:

return rootObj.getListA().stream()
.mapToInt(objA->objA.getListB().stream().mapToInt(ObjectB::getCount).sum()*objA.getCount())
.sum();

答案 1 :(得分:3)

这是一种替代解决方案,在许多情况下可能更为可取:

name: 'person'

答案 2 :(得分:2)

相当容易:将ObjectA映射到其ObjectB::getCount所有乘以getCount()的总和,然后简单地将IntStream求和:

int total = rootObj.getListA().stream()
    .mapToInt(obja -> obja.getCount() * obja.getListB().stream().mapToInt(ObjectB::getCount).sum())
    .sum();

为了提高可读性,您可以引入私有帮助方法:

int total = rootObj.getListA().stream()
    .mapToInt(this::calculate)
    .sum();

使用辅助方法:

private int calculate(ObjectA obja) {
    return obja.getListB().stream()
            .mapToInt(ObjectB::getCount)
            .sum() * obja.getCount();
}

答案 3 :(得分:2)

对于一次性走两个流的更一般的解决方案,这个不是很好但是它可以工作解决方案。

ssh