Java 8 flatMap + Optional.of not compiling

I am trying flatMap Optional in Java. Here is a simplified example:

 List<String> x = Arrays.asList("a", "b", "c"); List<String> result = x.stream().flatMap((val) -> val.equals("b") ? Optional.empty() : Optional.of(val)).collect(Collectors.toList()); 

I get this error message from the compiler:

 Error:(10, 27) java: incompatible types: no instance(s) of type variable(s) T exist so that java.util.Optional<T> conforms to java.util.stream.Stream<? extends R> 

What happened? Here is an example of what I'm trying to achieve in Scala:

 List("a", "b", "c").flatMap(x => if (x == "b") None else Some(x)) 

It returns:

 res2: List[String] = List(a, c) 

as was expected.

How do I convert this to Java so that it compiles?

+6
source share
2 answers

There is no need to deal with Optional .

The easiest direct solution is to use filter

 List<String> result = x.stream() .filter(val -> !val.equals("b")) .collect(Collectors.toList()); 

If you insist on using flatMap , you should just use Stream instead of Optional :

 List<String> result = x.stream().flatMap( val -> val.equals("b")? Stream.empty(): Stream.of(val)) .collect(Collectors.toList()); 

If you need to deal with an operation that inevitably creates Optional , you will have to convert it to Stream to use Stream.flatMap :

 List<String> result = x.stream() .map(val -> val.equals("b") ? Optional.<String>empty() : Optional.of(val)) .flatMap(o->o.map(Stream::of).orElse(Stream.empty())) .collect(Collectors.toList()); 
+2
source
Expected that

flatMap map the Stream input element to another Stream . Therefore, it should return Stream , not Optional .

Therefore, you should do something like this:

 List<String> x = Arrays.asList("a", "b", "c"); List<Optional<String>> result = x.stream() .flatMap((val) -> val.equals("b") ? Stream.of(Optional.empty()) : Stream.of(Optional.of(val))) .collect(Collectors.toList()); 

Note that if your goal is simply to get rid of some values โ€‹โ€‹("b" in your example), you do not have to use the "Advanced" parameter at all. You can simply filter the stream:

 List<String> result = x.stream() .filter (val -> !val.equals("b")) .collect(Collectors.toList()); 

This way you don't need flatMap , but your output is List<String> instead of List<Optional<String>> .

As Holger noted, the solution that Stream of Optional returns can be simplified by using map instead of flatMap , since each element maps to one Optional :

 List<String> x = Arrays.asList("a", "b", "c"); List<Optional<String>> result = x.stream() .map((val) -> val.equals("b") ? Optional.empty() : Optional.of(val)) .collect(Collectors.toList()); 
+6
source

Source: https://habr.com/ru/post/977360/


All Articles