En este post vamos a ver las distintas opciones para filtrar los valores no-empty de un Stream de Optional.
Para el ejemplo, usaremos la siguiente lista donde se puede ver que tenemos varios valores Optional.empty():
List<Optional<Integer>> numeros = Arrays.asList(
Optional.of(1),
Optional.empty(),
Optional.of(2),
Optional.of(3),
Optional.empty(),
Optional.of(4));
Filtrando Optional usando filter + map
Esta opción es la más intuitiva. Primero aplicamos un filter indicando que solo queremos los Optional que tengan valor, y a continuación aplicamos un map para obtener el valor correspondiente:
List<Integer> numerosSinOptional = numeros.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
Filtrando Optional usando Optional.stream y flatMap
Gracias a la operación Optional.stream (este método solo está disponible si estamos usando Java 9 o superior) convierte nuestro Optional en un Stream, devolviendo un Stream.empty() en caso de ser un Optional.empty(). Y con la operación flatMap pasamos de un Stream de Streams a un único Stream. Por tanto, lo que estamos haciendo es uniendo todos los streams que genera cada Optional::stream, y el propio flatMap, en caso de encontrarse Stream.empty ya no lo añade al Stream final. Por tanto, lo que antes eran 2 operaciones en el Stream ahora se traduce en una única operación:
List<Integer> numerosSinOptional = numeros.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Aunque esta operación pueda parecer menos intuitiva, resulta ser la opción más óptima.