What is the difference between Optional.flatMap() and Stream.flatMap().
Correct flatMap on Stream:
List<ObjectDTO> collect = types.stream()
.flatMap(a -> client.getSthById(new URI(a)).stream())
.collect(Collectors.toList());
Exception while using flatMap on Optional:
List<ObjectDTO> collect2 = client.getSthByObj(obje.get(), null).getBrowse()
.flatMap(uri -> client.getSthById(uri).stream())
.collect(Collectors.toList());
Why can't I use it in the same way?
It’s hard to be sure from your code snippets where we don’t know the types of the variables you use nor the return types of the methods. But I think that the source of your error is that you are trying to pass a lambda that returns a Stream
to Optional.flatMap()
.
Let’s look at Stream
first. Stream.flatMap()
takes a function that returns a Stream
. This seems to be exactly what you are giving it in your first code snippet.
Optional
on the other hand: Optional.flatMap()
requires a function that returns an Optional
. If getBrowse()
returns an Optional
, then what you pass to Optional.flatMap
is uri -> physicalInventoryClient.getSublocationsByIds(uri).stream()
. This looks like your lambda returns a stream, not an Optional
. When I try the same in my Eclipse, I get a compile error like the following:
The method flatMap(Function<? super String,? extends Optional<? extends U>>) in the type Optional<String> is not applicable for the arguments ((Object x) -> {})
The solution? From Java 9 Optional
has a stream
method that will probably let you achieve what you are trying. Again, without knowing your code it’s hard to suggest, but probably something like:
List<SublocationBrowseDTO> collect2 = physicalInventoryClient.getSublocationsByLocation(masterLocation.get(), null)
.getBrowse()
.stream()
.flatMap(uri -> physicalInventoryClient.getSublocationsByIds(uri).stream())
.collect(Collectors.toList());
Edit: Alternative without stream:
List<SublocationBrowseDTO> collect2 = physicalInventoryClient.getSublocationsByLocation(masterLocation.get(), null)
.getBrowse()
.map(uri -> physicalInventoryClient.getSublocationsByIds(uri))
.orElse(Collections.emptyList());
The latter version requires that getSublocationsById()
returns a list, but can probably be modified to work if the return type is something else. IMHO it’s a bit simpler.