Вопрос

This question is a follow-up to an earlier question: Adding up BigDecimals using Streams

The question related to adding up BigDecimals using Java 8 Streams and Lambda expressions. After implementing the answers given, I ran into another problem: whenever the stream is empty, the Optional::get() method throws a NoSuchElementException.

Consider the following code:

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());
}

The vanilla Java code has no problem with an empty collection, but the new Java 8 code does.

What is the most elegant way to avoid a NSEE here? Certainly we could do:

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

But is there a Java-8-ish way to handle empty collections?

Это было полезно?

Решение 2

While typing the example to ask the question, I found the answer:

Stream::reduce() returns an Optional which has a method: orElse(). So,

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

becomes

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

So I decided to post a Q-and-A.

Lambdas are great. +1 Java.

Другие советы

You should, in this case, not be using the version of reduce that can return an Optional<BigDecimal>.

You should be using the other version, as mentioned before, that provides an identity element in case the stream is empty, that is the whole reason the identity element is there.

So you want to have:

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

Instead of the old version.

In this case you do not care about whether the stream is empty or not, you just want a valid result.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top