在Java 8流中避免NoSuchElementException

ryv*_*age 3 java lambda java-8 java-stream

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

问题与BigDecimal使用Java 8 Stream和Lambda表达式添加s 有关.在实现给出的答案后,我遇到了另一个问题:每当流为空时,该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());
}
Run Code Online (Sandbox Code Playgroud)

vanilla Java代码对空集合没有问题,但新的Java 8代码可以.

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

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

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

ski*_*iwi 6

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

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

所以你想拥有:

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

而不是旧版本.

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

  • 是的,两个arg`reduce`形式(带有标识值)在这里是合适的.标识值不仅用于零元素流,而且还用作并行缩减时的部分结果的初始值. (2认同)

ryv*_*age 5

在输入示例来提问时,我找到了答案:

Stream::reduce()返回Optional一个方法:orElse().所以,

System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).get());
Run Code Online (Sandbox Code Playgroud)

System.out.println("Sum = " + values.stream().reduce((x, y) -> x.add(y)).orElse(BigDecimal.ZERO));
Run Code Online (Sandbox Code Playgroud)

所以我决定发布Q-and-A.

兰巴达很棒.+1 Java.

  • 错误是在一个可选项上调用get(),你不知道该东西是非空的.相反,使用其中一个条件方法,如orElse()或ifPresent(),或者基于Optional.isPresent()编写条件代码. (5认同)