In this article, we're going to talk about how to filter out non-empty values from a Stream of Optionals.
We'll be looking at three different approaches – two using Java 8 and one using the new support in Java 9.
We will be working on the same list in all examples:
List<Optional<String>> listOfOptionals = Arrays.asList( Optional.empty(), Optional.of("foo"), Optional.empty(), Optional.of("bar"));
2. Using filter()
One of the options in Java 8 is to filter out the values with Optional::isPresent and then perform mapping with the Optional::get function to extract values:
List<String> filteredList = listOfOptionals.stream() .filter(Optional::isPresent) .map(Optional::get) .collect(Collectors.toList());
3. Using flatMap()
The other option would be to use flatMap with a lambda expression that converts an empty Optional to an empty Stream instance, and non-empty Optional to a Stream instance containing only one element:
List<String> filteredList = listOfOptionals.stream() .flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty()) .collect(Collectors.toList());
Alternatively, you could apply the same approach using a different way of converting an Optional to Stream:
List<String> filteredList = listOfOptionals.stream() .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty)) .collect(Collectors.toList());
4. Java 9's Optional::stream
All this will get quite simplified with the arrival of Java 9 that adds a stream() method to Optional.
This approach is similar to the one showed in section 3 but this time we are using a predefined method for converting Optional instance into a Stream instance:
It will return a stream of either one or zero element(s) whether the Optional value is or isn't present:
List<String> filteredList = listOfOptionals.stream() .flatMap(Optional::stream) .collect(Collectors.toList());
With this, we've quickly seen three ways of filtering the present values out of a Stream of Optionals.
The full implementation of code samples can be found on the Github project.