使用 Java 流将双打映射汇总为聚合的 BigDecimal

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

我正在尝试使用 Java 8 Stream API mapToDouble 方法,如下所示:

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

问题是 Orderline::getPrice return 是 BigDecimal,而不是 Double。因此上面的尝试编译失败(Bad return type in method reference: cannot convert java.math.BigDecimal to doubele).

看到 Orderline#price 是一个 BigDecimal,我如何使用 Stream API(以及 mapToDouble 或类似的东西)来获取我的 totalCost?

您应该添加 BigDecimals 使用 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);

来自 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(a, b) -> a.add(b) 的缩写形式,即 returns a + b。另外,标识元素是 0BigDecimal.ZERO.

Eclipse Collections 与 Java 流结合使用,这将有效:

BigDecimal totalCost = order.getOrderlineList().stream()
    .collect(Collectors2.summingBigDecimal(Orderline::getPrice));

您还可以使用 Iterate class 稍微简化代码。

BigDecimal totalCost = Iterate.sumOfBigDecimal(order.getOrderlineList(), Orderline::getPrice)

注意:我是 Eclipse Collections 的提交者