3

这个问题是对较早问题的后续问题:使用 Streams 添加 BigDecimals

BigDecimal与使用 Java 8Stream和 Lambda 表达式加起来有关的问题。在实现给出的答案后,我遇到了另一个问题:只要流为空,该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());
}

普通 Java 代码对空集合没有问题,但新的 Java 8 代码可以。

在这里避免 NSEE 的最优雅的方法是什么?当然我们可以这样做:

System.out.println("Sum = " + values == null || values.isEmpty() ? 0 : values.stream().reduce((x, y) -> x.add(y)).get());

但是有没有一种 Java-8 的方式来处理空集合?

4

2 回答 2

6

在这种情况下,您应该使用reduce可以返回Optional<BigDecimal>.

如前所述,您应该使用另一个版本,该版本在流为空的情况下提供标识元素,这就是标识元素存在的全部原因。

所以你想拥有:

System.out.println("Sum = " + values.stream().reduce(BigDecimal.ZERO, (x, y) -> x.add(y));

而不是旧版本。

在这种情况下,您不关心流是否为空,您只需要一个有效的结果。

于 2014-03-25T18:21:14.143 回答
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));

所以我决定发布一个问答。

Lambda 很棒。+1 爪哇。

于 2014-03-25T18:12:40.613 回答