【问题标题】:Summing a map of doubles into an aggregated BigDecimal with Java Streams [duplicate]使用 Java Streams 将双精度图求和为聚合的 BigDecimal [重复]
【发布时间】:2019-11-07 15:10:03
【问题描述】:

我正在尝试像这样使用 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

【问题讨论】:

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


    【解决方案1】:

    您应该使用BigDecimal.add() 添加BigDecimals,而不是将它们转换为双精度并再次返回以避免舍入错误。总结所有价格,您可以使用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

    【讨论】:

    • 谢谢@Samuel,你能(或任何人!)向我解释一下reduce()在那里做什么?
    • @hotmeatballsoup 是的,当然,我更新了我的答案,希望它有助于理解。如果需要,请随时要求进一步澄清。
    【解决方案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 的提交者

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-24
      • 1970-01-01
      • 1970-01-01
      • 2018-01-11
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多