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

时间:2019-06-25 18:10:25

标签: java java-8 sum java-stream bigdecimal

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

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

问题是Orderline::getPrice返回BigDecimal,而不是Double。因此,以上尝试无法编译(方法参考中的错误返回类型:无法将java.math.BigDecimal转换为doubele )。

看到Orderline#priceBigDecimal,如何使用Stream API(以及mapToDouble或类似的东西)来获取我的totalCost

2 个答案:

答案 0 :(得分:5)

您应该使用BigDecimal.add()添加BigDecimal,而不是将它们转换为double并再次返回,以避免舍入错误。要汇总所有价格,您可以使用Stream.reduce()

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

摘自Stream.reduce()的文档:

  

使用提供的标识值和关联累加函数对此流的元素进行缩减,并返回缩减后的值。这等效于:

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

BigDecimal::add(a, b) -> a.add(b)的缩写,它只返回a + b。另外,标识元素为0BigDecimal.ZERO

答案 1 :(得分:2)

Eclipse Collections与Java Streams结合使用,将会起作用:

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

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

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

注意:我是Eclipse Collections的提交者