Search code examples
javajava-stream

What is the difference between using Stream.ofNullable() and stream()?


While working with Streams in Java 11, I noticed the following situation. I'm trying to use the Stream API in two different ways on a non-null list.

First way:

Collection<Object> categoryIds = List.of(1L, 2L, 3L, 4L);

List<String> nullable = Stream.ofNullable(categoryIds)
        .map(Object::toString)
        .collect(Collectors.toList());

Second way:

Collection<Object> categoryIds = List.of(1L, 2L, 3L, 4L);

List<String> nullable = categoryIds.stream()
        .map(Object::toString)
        .collect(Collectors.toList());

The two ways I tried lead to two different results. The resulting list of the first way is a string containing a single element. This string is: "[1, 2, 3, 4]" The second way gives the desired and expected results. Returns a result list with 4 elements: "1", "2", "3", "4".

Is this behavior expected? Or is it a problem?


Solution

  • Stream.ofNullable you are creating a Stream object with single element or empty Stream for null object

    Returns a sequential Stream containing a single element, , if non-null, otherwise returns an empty Stream.

    If you want to get the same output using Stream.ofNullable you need to flatten the list using flatMap

    List<String> nullable = Stream.ofNullable(categoryIds)
        .flatMap(List::stream)
        .map(Object::toString)
        .collect(Collectors.toList());
    

    Collection.stream - it creates the stream object with collection elements in sequential order

    Returns a sequential Stream with this collection as its source.

    And the Collection.stream is equivalent to stream.of(T... values) method

     List<String> nullable = Stream.of(1L, 2L, 3L, 4L) // or categoryIds.stream()
        .map(Object::toString)
        .collect(Collectors.toList());