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 String
s 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 Optional
s (unless you wish to transform them to null
s).
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
Best Language to Parse Extremely Large Excel 2007 Files
Spring 4 - Addresourcehandlers Not Resolving the Static Resources
Jtable How Prepareeditor Works
How to Use 3Rd Party Library in Java9 Module
Time Complexity for Java Arraylist
How to Add Days to a Date in Java
Gson.Tojson() Throws Stackoverflowerror
Auto Adjust the Height of Rows in a Jtable
Building an Uberjar with Gradle
Creating New Generic Object with Wildcard
Jce Cannot Authenticate the Provider Bc in Java Swing Application
How Is Driver Class Located in Jdbc4
Formatting a String to a Currency Format in Jasper Report
How to Redirect to Another Action Class Without Using on Struts.Xml