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

Jac*_*ack 4 java collections sum java-8 java-stream

我相信我可以在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)
Run Code Online (Sandbox Code Playgroud)

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

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

Tun*_*aki 7

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

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

class ResultHolder {
    List<BigDecimal> list = new ArrayList<>();
    BigDecimal sum = BigDecimal.ZERO;
}
Run Code Online (Sandbox Code Playgroud)

最后,我们可以使用它:

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);
Run Code Online (Sandbox Code Playgroud)

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


Sle*_*idi 6

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

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

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