Summing a map of doubles into an aggregated BigDecimal with Java Streams

hotmeatballsoup :

I'm trying to use the Java 8 Stream API mapToDouble method like so:

BigDecimal totalCost = order.getOrderlineList().stream()
    .mapToDouble(Orderline::getPrice)
    .sum();

The problem is that Orderline::getPrice returns a BigDecimal, not a Double. Hence the attempt above fails to compile (Bad return type in method reference: cannot convert java.math.BigDecimal to doubele).

Seeing that Orderline#price is a BigDecimal, how can I use the Stream API (and either mapToDouble or something similar) to get my totalCost?

Samuel Philipp :

You should add BigDecimals using BigDecimal.add() instead of converting them to double and back again to avoid rounding errors. To sum all prices you can use Stream.reduce():

BigDecimal bigDecimal = order.getOrderLines().stream()
        .map(OrderLine::getPrice)
        .reduce(BigDecimal.ZERO, BigDecimal::add);

From the docs of Stream.reduce():

Performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value. This is equivalent to:

T result = identity;
for (T element : this stream)
    result = accumulator.apply(result, element)
return result;

BigDecimal::add is a short form of (a, b) -> a.add(b), which simply returns a + b. For addition the identity element is 0 or BigDecimal.ZERO.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=122483&siteId=1