0

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?

Kuba
  • 39
  • 6
  • 2
    what are you asking? this is really unclear, and did you read the docs and numerous other posts here about one and the other? – Eugene Jun 26 '18 at 10:47
  • 2
    They perform very similar operations, hence the same name. The main difference is that one requires an `Optional` and a method that returns an `Optional` while the other requires a `Stream` and a method that returns a `Stream`. – Ole V.V. Jun 26 '18 at 11:12
  • 1
    Could you elaborate your examples into [MCVE](https://stackoverflow.com/help/mcve)? That would help. – Ole V.V. Jun 26 '18 at 11:14
  • Also the stacktrace from the exception that you say that you get would be helpful. – Ole V.V. Jun 27 '18 at 10:56
  • 1
    It would be good that you clarify your question to indicate exactly what you are trying to do, and give self-sufficient code snippets that show your problem ([mcve]). Even if you already got your answer, that will be helpful for future readers. – Didier L Jun 27 '18 at 12:26

3 Answers3

1

Optional and Stream are 2 different beasts intended for separated purposes.

Optional is a Wrapper that holds a result that can be or not be "present" (null) and provided methods to deal which these 2 conditions (present, or Not Present). the "flatMap()" operation is an operation applied to the value held in your Optional wrapper. that operation must return an Optional as result:

Optional<String> s = Optional.of("test input");
s.flatMap( input -> Optional.of(input));

read here for more infos on Optional.flatMap();

Stream' flatmap() helps you to get and process nested elements of list elements. see here for more explanation and explanations of Stream's flatmap().

arthur
  • 3,117
  • 4
  • 24
  • 33
1

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.

Ole V.V.
  • 76,217
  • 14
  • 120
  • 142
  • Excuse me, that was my first question in stackoverflow. This answer fulfills my expectations. Thank you so much! – Kuba Jun 27 '18 at 11:49
  • We’re all learning. And yes, it takes a bit to learn how to use this site. Welcome! BTW I thought of a different solution and added it to the answer. – Ole V.V. Jun 27 '18 at 13:51
0

From the javadoc: Optional.flatMap:

flatMap(Function<? super T,Optional<U>> mapper)

If a value is present, apply the provided Optional-bearing mapping function to it, return that result, otherwise return an empty Optional.

Stream.flatMap:

flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

So the main difference is, that one returns a Stream, the other an Optional

keuleJ
  • 3,247
  • 4
  • 28
  • 50