Differencebetween Optional.Flatmap and Optional.Map

What is the difference between Optional.flatMap and Optional.map?

Use map if the function returns the object you need or flatMap if the function returns an Optional. For example:

public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}

static String getOutput(String input) {
return input == null ? null : "output for " + input;
}

static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}

Both print statements print the same thing.

Java8 :: flatMap in optional

See the signature of flatMap:

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

The Function is supposed to return an Optional, so in order to use it, you'll need to write:

Optional.ofNullable(project)
.map(prjct-> prjct.getApplciationType())
.flatMap(appType1 -> Optional.ofNullable(appType1.getDirectory()))
.ifPresent(e -> System.out.println(e));

Of course, using map makes more sense in this example (as in your first snippet, which passes compilation).

Whats the difference between Optional.flatMap() and Stream.flatMap()

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.

What's the difference between map() and flatMap() methods in Java 8?

Both map and flatMap can be applied to a Stream<T> and they both return a Stream<R>. The difference is that the map operation produces one output value for each input value, whereas the flatMap operation produces an arbitrary number (zero or more) values for each input value.

This is reflected in the arguments to each operation.

The map operation takes a Function, which is called for each value in the input stream and produces one result value, which is sent to the output stream.

The flatMap operation takes a function that conceptually wants to consume one value and produce an arbitrary number of values. However, in Java, it's cumbersome for a method to return an arbitrary number of values, since methods can return only zero or one value. One could imagine an API where the mapper function for flatMap takes a value and returns an array or a List of values, which are then sent to the output. Given that this is the streams library, a particularly apt way to represent an arbitrary number of return values is for the mapper function itself to return a stream! The values from the stream returned by the mapper are drained from the stream and are passed to the output stream. The "clumps" of values returned by each call to the mapper function are not distinguished at all in the output stream, thus the output is said to have been "flattened."

Typical use is for the mapper function of flatMap to return Stream.empty() if it wants to send zero values, or something like Stream.of(a, b, c) if it wants to return several values. But of course any stream can be returned.

Java 8 Optional and flatMap - what is wrong?

You can use map to perform the desired operation. The map operation will not take place if the Optional is empty but leave again an empty Optional. You can provide the fallback value afterwards:

player.map(p -> teamDAO.findPlayers(p.team)).orElse(Collections.emptyList())

The mapping from a List of Player to a List of Player’s name Strings can’t be performed by an Optional; that’s a Stream task:

Optional<Player> player = Optional.ofNullable(playerDAO.get(playerName));
return player.map(p -> teamDAO.findPlayers(p.team)
.stream().map(tp -> tp.name).collect(Collectors.toList()))
.orElse(Collections.emptyList());

Map and flatMap difference in optional unwrapping in Swift 1.2

(Remark: The answer has been updated to reflect the syntax changes in Swift 3 and later, such as the abolishment of ImplicitlyUnwrappedOptional.)

Optional.map() and Optional.flatMap() are declared as follows (I have omitted the throws/rethrows modifiers which are irrelevant here):

func map<U>(_ transform: (Wrapped) -> U) -> U?
func flatMap<U>(_ transform: (Wrapped) -> U?) -> U?

Let's consider a simplified version of your first example using “map”:

let number: Int? = 1
let res1 = number.map { $0 + 1 }
print(res1) // Optional(2)

number has the type Int? and the closure type is inferred as (Int) -> Int. U is Int, and the type of the return value is Int?. number is not nil, so it is unwrapped and passed 1 is passed to the closure. The closure returns 2 and map returns Optional(2). If number were nil then the result would be nil.

Now we consider a simplified version of your second example with “flatMap”:

let number: Int? = 1
let res2 = number.flatMap { $0 + 1 }
print(res2) // Optional(2)

flatMap expects a closure of type (Wrapped) -> U?, but { $0 + 1 } does not return an optional. In order to make it compile, the compiler converts this to

let res2 = number.flatMap { return Optional($0 + 1) }

Now the closure has type (Int) -> Int?, and U is Int again. Again, number is unwrapped and passed to the closure. The closure returns Optional(2) which is also the return value from flatMap. If number were nil or if the closure would return nil then the result would be nil.

So there is indeed no difference between these invocations:

let res1 = number.map { $0 + 1 }
let res2 = number.flatMap { $0 + 1 }

However that is not what flatMap is meant for. A more realistic example would be

func foo(_ s : String?) -> Int? {
return s.flatMap { Int($0) }
}

print(foo("1")) // Optional(1)
print(foo("x")) // nil (because `Int($0)` returns nil)
print(foo(nil)) // nil (because the argument is nil)

Generally, map takes a closure of type (Wrapped) -> U and transforms

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> Optional<U>.some(transform(wrapped))

flatMap takes a closure of type (Wrapped) -> U? and transforms

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> transform(wrapped)

Here transform(wrapped) can be Optional<U>.none as well.

If (as in your example) flatMap is called with a closure which does not return an optional then the compiler converts it to an optional automatically, and there is no difference to map anymore.

Using Java 8's Optional with Stream::flatMap

Java 9

Optional.stream has been added to JDK 9. This enables you to do the following, without the need of any helper method:

Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();

Java 8

Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional<T> into a zero-or-one length Stream<T>. You could do this:

Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();

Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:

/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}

Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();

Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.

What are differences between mono.map and java optional.map. can it be used combined with Java Optionnal?

map takes one item and potentially transforms it into a different item and returns it into the starting context.

Mono/Flux are not allowed to contain null values. Instead we use Mono.empty() to represent nothing.

When you put something in a Mono and use map, your code is living in the reactive context which means that the server can optimize its usage of threads to the max.

While in you second example you put something into a Optional<T> and then do all the transformations outside the reactive context and when you are done you put the result into the reactive context with Mono#just.

The second example is what i call fake reactive code. Its when people do all the things they want to to using old imperative java and then place the end result in a Mono.

That is not reactive

The more time you spend inside the reactive context, the more the framework can optimize its resource usage.

In your case you should use the first example and handle the potential null values in each mapping function, by checking for it and returning a Mono.empty() instead.

Java's flatMap on list of list of optional integers

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());

Why are Optional's or and flatMap methods' supplier type parameters wildcards?

I found the reasoning behind this from Stuart Marks himself

http://mail.openjdk.java.net/pipermail/core-libs-dev/2016-October/044026.html

This has to do with nested generics (Optional is nested within Function).
From the mail thread

 Function<..., Optional<StringBuilder>>

is not a subtype of

 Function<..., Optional<? extends CharSequence>>

To get around this, we have to add the outer wildcard as well, so that

 Function<..., Optional<StringBuilder>>

is a subtype of

 Function<..., ? extends Optional<? extends CharSequence>>


Related Topics



Leave a reply



Submit