繁体   English   中英

Java 8 Stream将元素添加到列表和求和

[英]Java 8 Stream add elements to list and sum

我相信我可以在listOfPricedObjects上使用一个流操作来做下一步:

List<BigDecimal> myList = new ArrayList();
myList = listOfPricedObjects.stream().map(PricedObject::getPrice).collect(Collectors.toList());
BigDecimal sum = listOfPricedObjects.stream().map(PricedObject::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add)

我如何用价格填充myList并使用流一次计算价格总和? 谢谢

UPD:结果我需要myList填充价格和sum变量和sum。 但不是两次使用stream()。

你想要的是在2个收藏家中收集你的元素:第一个收集到列表中,第二个收集价格。

由于Stream API本身没有这样的收集器,我们可以轻松构建自己的收集器。 让我们创建一个类ResultHolder ,它将保存Stream管道的结果:这是小数列表和总和。

class ResultHolder {
    List<BigDecimal> list = new ArrayList<>();
    BigDecimal sum = BigDecimal.ZERO;
}

最后,我们可以使用它:

ResultHolder resultHolder = 
    listOfPricedObjects.stream()
            .map(PricedObject::getPrice)
            .collect(
                ResultHolder::new,
                (r, p) -> { r.list.add(p); r.sum = r.sum.add(p); },
                (r1, r2) -> { r1.list.addAll(r2.list); r1.sum = r1.sum.add(r2.sum); }
            );
System.out.println(resultHolder.list);
System.out.println(resultHolder.sum);

这将在并行管道中工作,并将保持列表的初始顺序,与其他答案相反。

您可以使用peek并在应用缩减时添加到新list

List<BigDecimal> newList = new ArrayList<>();
BigDecimal sum = list.stream()
                     .map(PricedObject::getPrice)
                     .peek(newList::add)
                     .reduce(BigDecimal.ZERO, BigDecimal::add);

如果你对使用带有非并发集合的parallelStream感兴趣请查看Tunaki答案,这是有意义的,因为sum是一个令人尴尬的并行任务。

虽然假设无法从源重新创建像listOfPricedObjects这样的任意流并且因此只遍历一次的用例可能是合理的,您可以安全地假设遍历通过Collectors.toList()生成的列表可以有效地遍历:

List<BigDecimal> myList = listOfPricedObjects.stream()
    .map(PricedObject::getPrice).collect(Collectors.toList());
BigDecimal sum = myList.stream().reduce(BigDecimal::add).orElse(BigDecimal.ZERO);

这里没有代码重复,并且在一次流遍历中执行这两个不相关的操作的任何尝试都会使代码更复杂而没有任何好处。

您可以执行标识映射,将直通值添加到列表中

BigDecimal sum = listOfPricedObjects.stream()
                                    .map(o -> {
                                         myList.add(o); 
                                         return o;})
                                    .map(PricedObject::getPrice)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add)

但我会选择使用peek()的Sleiman Jneidi解决方案,它更优雅

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM