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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With