Java Stream - How to produce Null as a result using reduce() when the Stream is Empty with Java 8

Viewed 50

I have the following snippet of code, where items is a list of type List<BigDecimal>:

BigDecimal output = items.stream()
    .filter(Objects::notnull)
    .reduce(BigDecimal.ZERO, BigDecimal::add);

And I have the following test cases:

a. Input -> List<BigDecimal> items = Arrays.asList(null, 4);
   Expected output: 4

b. Input -> List<BigDecimal> items = Arrays.asList(null, 4, 3);
   Expected output: 7

c. Input -> List<BigDecimal> items = Arrays.asList(null, null);
   Expected output: null

My code is failing for test-case C, the output it produces is a BigDecimal having the value of 0 instead of null.

How can I fix that?

1 Answers

Since you have provided the identity (the first argument of the reduce(), which serves as the starting point for folding a stream) as BigDecimal.ZERO, it would be returned in case when the stream is empty.

We can use another flavor of reduce(accumulator) which expect only one argument - accumulator function, and returns an Optional. This version treats the first stream element that reaches it as an identity, and if the stream appears to be empty, the method would return an empty optional.

To return null as default value if the stream is empty, we can apply orElse() method on the optional result returned by reduce().

BigDecimal output = items.stream()
    .filter(Objects::nonNull) // produces a stream of non-null elements
    .reduce(BigDecimal::add)  // Optional<BigDecimal>
    .orElse(null);            // BigDecimal
Related