我们假设我有一个这样的课程:
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
所以我应该为此创建一个特定的比较器?
答案 0 :(得分:16)
我要做的是检查可选
Optional<BigDecimal> max = brol.stream()
.map(a -> a.amount)
.max(Comparator.naturalOrder());
if (max.isPresent()) {
// have a max
}
如果您觉得这更清楚,可以使用Comparator.naturalOrder()
代替BigDecimal::compare
。
Optional.get()抛出NoSuchElementException
,因为没有元素。当您获得最大值的对象不是Comparator
Comparable
在这种情况下,您不需要最大A
amount
BigDecimal
Comparable
min()
。
你可以提供一个比较器,如果你真的想要最小值,虽然使用items = ['item1', 'item2', 'item3', 'item4'];
currentItem = 'item3';
在这方面是一个更简单的选择。
答案 1 :(得分:3)
您不需要特定的比较器。比较器不是你的问题。
流畅的调用风格很好,时髦而且时髦,但它有一个主要的缺点,许多人似乎忽略了:当这一系列函数调用发生错误时,你不知道它发生的地方。
因此,为了解决这些问题,最好将流畅的火车分解成单独的货车。 (至少在故障排除方面,如果您愿意,请将其放回列车中,所有故障排除工作都已完成。)
在这种情况下,您会看到max()
返回Optional<BigDecimal>
,而Optional
是ArrayList
因为brol
max
为空,(并且您提供的示例,它是空的,然后没有最大值,因为ArrayList
操作在空列表中未定义。
因此,您需要提供stream().max()
为空的情况。你可以在调用isPresent()
之前执行此操作,或者可以像Peter Lawrey建议的那样,通过调用Optional
的{{1}}方法来执行此操作。
顺便说一下,你犯这个错误的事实表明:
您正在使用一些过时的构建工具,这些工具无法向您发出有关代码的警告,或者
您没有启用所有警告,或
您收到警告但忽略了它们。
.get()
在没有.isPresent()
的情况下被调用。因此,我可以在编译代码之前,在运行代码之前,在对其进行故障排除之前,以及在询问有关它的stackoverflow问题之前,立即告诉代码有什么问题。