Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Stream add elements to list and sum

I believe I can do next using one stream operation on 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)

How I can fill myList with prices and calculate sum of prices using stream one time? Thanks

UPD: As the result I need myList filled with prices and sum variable with sum. But not with usding stream() twice for that.

like image 903
Jack Avatar asked Dec 01 '22 16:12

Jack


1 Answers

What you want here is to collect your elements inside 2 collectors: the first one would collect into a list, and the second one would sum the price.

Since there are no such collectors in the Stream API itself, we can easily construct our own. Let's create a class ResultHolder that will hold the result of the Stream pipeline: this is the list of decimals and the sum.

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

Finally, we can use it with:

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);

This will work in a parallel pipeline and will keep the initial order of the list, contrary to the other answers.

like image 81
Tunaki Avatar answered Dec 04 '22 11:12

Tunaki