Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Java's Stream.collect() return null?

The JavaDoc for Stream.collect() says that it returns "the result of the reduction". That doesn't tell me if code like this can return null for filteredList:

List<String> filteredList = inputList.stream()     .filter(c -> c.isActive())     .collect(Collectors.toList()); 

I would expect that if it could return null then it would return an Optional, but it doesn't say that either.

Is it documented anywhere whether Stream.collect() can return null?

like image 496
Dean Schulze Avatar asked May 09 '18 15:05

Dean Schulze


People also ask

Does collect return null?

Return value of the Function<T,R> will be return value of collect(). Show activity on this post. I think this part of the documentation says that it cannot be null: Returns a Collector that accumulates the input elements into a new List.

Can a stream contain null?

Designers of the API did not want to assume whether null means the value is not present (absent value) or is present but equals null. Also, you can still use map(Optional::isNullable) on any stream.

How do you handle null in stream filters?

We can use lambda expression str -> str!= null inside stream filter() to filter out null values from a stream.

What stream collect returns?

We can use Stream collect() function to perform a mutable reduction operation and concatenate the list elements. The supplier function is returning a new StringBuilder object in every call. The accumulator function is appending the list string element to the StringBuilder instance.


2 Answers

Collector.toList() will return an empty List for you.

Here is the implementation:

public static <T> Collector<T, ?, List<T>> toList() {     return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,                                (left, right) -> { left.addAll(right); return left; },                                CH_ID); } 

As you can see ArrayList::new is being used as a container for your items.

From JavaDoc of Collector:

A mutable reduction operation that accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed. Reduction operations can be performed either sequentially or in parallel.

A Collector is specified by four functions that work together to accumulate entries into a mutable result container, and optionally perform a final transform on the result. They are:

  • creation of a new result container (supplier())

  • incorporating a new data element into a result container (accumulator())

  • combining two result containers into one (combiner())
  • performing an optional final transform on the container (finisher())

And

A sequential implementation of a reduction using a collector would create a single result container using the supplier function, and invoke the accumulator function once for each input element. A parallel implementation would partition the input, create a result container for each partition, accumulate the contents of each partition into a subresult for that partition, and then use the combiner function to merge the subresults into a combined result.

So as long as you don't do weird things like combine function return null, the Collector always return at least a mutable container using your provided supplier function.

And I think it's very counter-intuitive if an implementation would ever return null container.

like image 158
Mạnh Quyết Nguyễn Avatar answered Oct 04 '22 14:10

Mạnh Quyết Nguyễn


This is not dependent on Stream.collect, but on the individual Collector. Collectors.toList() will return an empty ArrayList.

That said, there's no reason someone couldn't use a weird Collector to return null in certain circumstances:

.collect(     Collector.of(         ArrayList::new,         ArrayList::add,         (a, b) -> {             a.addAll(b);             return a;         },         a -> a.isEmpty() ? null : a  // finisher replaces empty list with null     ) ); 

So the Collector is the thing you need to remember to check. I believe all of the Collectors available out-of-the-box will return empty collections, as you'd expect.

like image 34
Michael Avatar answered Oct 04 '22 14:10

Michael