Java's flatMap on list of list of optional integers

Max Power :

I have the following bit of simplified code that fails to compile and I don't understand why:

List<Optional<Integer>> list =
    new ArrayList<>();
List<Integer> flattened = 
  list
    .stream()
    .flatMap(i -> i)
    .collect(Collectors.toList());

The compiler tells me:

[ERROR] ... incompatible types: cannot infer type-variable(s) R
[ERROR]     (argument mismatch; bad return type in lambda expression
[ERROR]       Optional<Integer> cannot be converted to Stream<? extends R>)
[ERROR]   where R,T are type-variables:
[ERROR]     R extends Object declared in method <R>flatMap(Function<? super T,? extends Stream<? extends R>>)
[ERROR]     T extends Object declared in interface Stream

I admit I'm not used to Java but I have to for a project. I mocked this in Scala where list.flatten and the equivalent list.flatMap(i => i) work just as expected:

val list = List(Some(1), Some(2), None)
list.flatten // List(1, 2)

Is Java's flatMap different?

Eran :

It should be:

List<Integer> flattened = 
  list
    .stream()
    .filter (Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

Your flatMap expects a function that transforms a Stream element to a Stream. You should use map instead (to extract the value of the Optional). In addition, you need to filter out empty Optionals (unless you wish to transform them to nulls).

Without the filtering:

List<Integer> flattened = 
  list
    .stream()
    .map(o -> o.orElse(null))
    .collect(Collectors.toList());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=37109&siteId=1