【问题标题】:Find max on BigDecimal list using java 8使用 java 8 在 BigDecimal 列表中查找最大值
【发布时间】:2017-08-04 21:04:04
【问题描述】:

假设我有这样的课程:

public class A {
    private int id;
    private BigDecimal amount;
}

我有一个List<A>。如何使用 Java 8 流找到列表中所有 A 对象的最大数量?

这个方法:

List<A> brol = new ArrayList<>();
BigDecimal max = brol.stream().max(Comparator.comparing(A -> A.getAmount())).get().getAmount();
        System.out.println("MAX = " + max);

NoSuchElementException 所以我应该为此创建一个特定的比较器?

【问题讨论】:

    标签: java java-8 java-stream


    【解决方案1】:

    我要做的是检查可选

    Optional<BigDecimal> max = brol.stream()
                                   .map(a -> a.amount)
                                   .max(Comparator.naturalOrder());
    if (max.isPresent()) {
       // have a max
    }
    

    如果您觉得这更清楚,可以使用BigDecimal::compare 而不是Comparator.naturalOrder()

    Optional.get() 正在抛出 NoSuchElementException,因为没有元素。当您获得最大值的对象不是Comparable 时,您只需要提供Comparator

    在这种情况下,您不需要最大 A,只需要最大 amount,即 BigDecimal,即 Comparable

    如果你真的想要最小值,你可以提供一个比较器,尽管在这方面使用 min() 会是一个更简单的选择。

    【讨论】:

    • 为了完整起见:OP 得到一个NoSuchElementException,因为他得到一个空列表的最大值,它确实返回一个Optional.empty(因为没有要返回的项目) .只要列表至少有 1 个项目,异常就应该消失。查看documentation关于max()
    • @PeterLawrey .max() 方法应该接收 Comparator 作为参数,不是吗?
    • @GrechkaVassili 不,因为由于map() 它正在比较实现ComparableBigDecimal
    • @Kayaman @PeterLawrey 谢谢,我已经解决了我的问题,但是当我尝试你的解决方案 Optional&lt;BigDecimal&gt; maximum = brol.stream().map(A -&gt; A.getAmount()).max(); 时,Intellij 给了我这个错误:method max in interface java.util.stream.Stream&lt;T&gt; cannot be applied to given types 它说 max() 方法应该收到java.util.Comparator&lt;? super.java.math.BigDecimal&gt;....
    • 啊,该死的,没有非比较者将max() 用于比较。那么你确实需要比较器。
    【解决方案2】:

    您不需要为此使用特定的比较器。比较器不是你的问题。

    流畅的调用风格既漂亮又时髦,但它有一个许多人似乎忽略的主要缺点:当在这一系列函数调用中的某个地方发生错误时,你不知道它发生在哪里。

    因此,为了解决此类问题,最好将流畅的火车分解成单独的货车。 (至少对于故障排除,如果您愿意,可以将其放回火车上,所有故障排除都已完成。)

    在这种情况下,您将看到max() 返回一个Optional&lt;BigDecimal&gt;,它是Optional,因为如果您的ArrayList brol 是空的,(在您提供的示例中,它是空的,)那么没有最大值,因为max 操作在一个空列表上是未定义的。

    因此,您需要提供ArrayList 为空的情况。您可以在调用 stream().max() 之前执行此操作,或者您可以按照 Peter Lawrey 的建议执行此操作,方法是调用 OptionalisPresent() 方法。

    顺便说一句,您犯此错误的事实表明:

    • 您正在使用一些过时的构建工具,这些工具无法就您的代码向您发出警告,或者

    • 您没有启用所有警告,或者

    • 您收到警告但忽略了它们。

    不要那样做,这样你永远不会走得太远。我的 IntelliJ IDEA 在您的代码上给了我一个警告(JetBrains 称之为“检查”),说在没有 .isPresent() 的情况下调用了 .get()。因此,我可以在编译代码之前、运行代码之前、排除故障之前以及询问有关它的 stackoverflow 问题之前立即判断代码有什么问题。

    【讨论】:

    • 你是对的!抱歉,有时由于注意力不集中的错误,您无法进行某些思考。我的brol 列表在另一个List&lt;A&gt; 之后被声明,实际上是空的。我也在使用 Intellij,但出现错误 Optional.get() without isPresent()...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 2017-09-25
    • 1970-01-01
    • 2013-11-16
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多