此问题是对早期问题的跟进:Adding up BigDecimals using Streams
与使用Java 8 BigDecimal
和Lambda表达式添加Stream
相关的问题。在实现给出的答案后,我遇到了另一个问题:每当流为空时,Optional::get()
方法抛出NoSuchElementException
。
请考虑以下代码:
public static void main(String[] args){
LinkedList<BigDecimal> values = new LinkedList<>();
// values.add(BigDecimal.valueOf(.1));
// values.add(BigDecimal.valueOf(1.1));
// values.add(BigDecimal.valueOf(2.1));
// values.add(BigDecimal.valueOf(.1));
// Classical Java approach
BigDecimal sum = BigDecimal.ZERO;
for(BigDecimal value : values) {
System.out.println(value);
sum = sum.add(value);
}
System.out.println("Sum = " + sum);
// Java 8 approach
values.forEach((value) -> System.out.println(value));
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).get());
}
vanilla Java代码对空集合没有问题,但新的Java 8代码可以。
在这里避免使用NSEE最优雅的方法是什么?我们当然可以做到:
System.out.println("Sum = " + values == null || values.isEmpty() ? 0 : values.stream().reduce((x, y) -> x.add(y)).get());
但是有没有一种Java-8-ish方式来处理空集合?
答案 0 :(得分:6)
在这种情况下,不应该使用可以返回reduce
的{{1}}版本。
你应该使用前面提到的另一个版本,它提供了一个标识元素,以防流是空的,这就是identity元素存在的全部原因。
所以你想拥有:
Optional<BigDecimal>
而不是旧版本。
在这种情况下,您不关心流是否为空,您只需要一个有效的结果。
答案 1 :(得分:5)
在输入示例来提问时,我找到了答案:
Stream::reduce()
返回Optional
,其中包含orElse()
方法。所以,
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).get());
变为
System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).orElse(BigDecimal.ZERO));
所以我决定发布一个Q-and-A。
Lambdas很棒。 +1 Java。