What's the difference between these two methods: Optional.flatMap() and Optional.map()?
An example would be appreciated.
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.
They both take a function from the type of the optional to something.
map() applies the function "as is" on the optional you have:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
What happens if your function is a function from T -> Optional<U>?
Your result is now an Optional<Optional<U>>!
That's what flatMap() is about: if your function already returns an Optional, flatMap() is a bit smarter and doesn't double wrap it, returning Optional<U>.
It's the composition of two functional idioms: map and flatten.
Okay. You only need to use 'flatMap' when you're facing nested Optionals. Here's the example.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
Like Stream, Optional#map will return a value wrapped by a Optional. That's why we get a nested Optional -- Optional<Optional<Insurance>. And at ②, we want to map it as an Insurance instance, that's how the tragedy happened.
The root is nested Optionals. If we can get the core value regardless the shells, we'll get it done. That's what flatMap does.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
In the end, I stronly recommed the Java 8 In Action to you if you'd like to study Java8 Systematicly.
Note:- below is the illustration of map and flatmap function, otherwise Optional is primarily designed to be used as a return type only.
As you already may know Optional is a kind of container which may or may not contain a single object, so it can be used wherever you anticipate a null value(You may never see NPE if use Optional properly). For example if you have a method which expects a person object which may be nullable you may want to write the method something like this:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
Here you have returned a String type which is automatically wrapped in an Optional type.
If person class looked like this, i.e. phone is also Optional
class Person{
private Optional<String> phone;
//setter,getter
}
In this case invoking map function will wrap the returned value in Optional and yield something like:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS;
Never call get method (if you need to) on an Optional without checking it with isPresent() unless you can't live without NullPointerExceptions.
What helped me was a look at the source code of the two functions.
Map - wraps the result in an Optional.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flatMap - returns the 'raw' object
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
Optional.map():
Takes every element and if the value exists, it is passed to the function:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Now added has one of three values: true or false wrapped into an Optional , if optionalValue was present, or an empty Optional otherwise.
If you don't need to process the result you can simply use ifPresent(), it doesn't have return value:
optionalValue.ifPresent(results::add);
Optional.flatMap():
Works similar to the same method of streams. Flattens out the stream of streams. With the difference that if the value is presented it is applied to function. Otherwise, an empty optional is returned.
You can use it for composing optional value functions calls.
Suppose we have methods:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
Then you can compute the square root of the inverse, like:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
or, if you prefer:
Optional<Double> result = Optional.of(-4.0)
.flatMap(MyMath::inverse)
.flatMap(MyMath::squareRoot);
If either the inverse() or the squareRoot() returns Optional.empty(), the result is empty.
You can refer below link to understand in detail (best explanation which I could find):
https://www.programmergirl.com/java-8-map-flatmap-difference/
Both map and flatMap - accept Function. The return type of map() is a single value whereas flatMap is returning stream of values
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
They do the same thing.
The only difference is that, the lambda return's type is wrapped by Optional or not.
For normal usage, map is shorter than flatMap
Example:
package bj;
import java.util.Optional;
import static java.lang.System.out;
public class App {
public static void main(String[] args) {
out.println(Optional.of(10).map (x -> x * x));
out.println(Optional.of(10).flatMap(x -> Optional.of(x * x)));
out.println(Optional.of(10).map (x -> Optional.of(x * x).get()));
out.println(Optional.<Integer>empty().map (x -> x * x));
out.println(Optional.<Integer>empty().flatMap(x -> Optional.of(x * x)));
out.println(Optional.<Integer>empty().map (x -> Optional.of(x * x).get()));
}
}
Output:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty
Related
Is it possible to check if the given string matches one of enum-names and then return that enum-element?
I tried this:
boolean isValid = Stream.of(Seniority.values())
.map(Seniority::name)
.collect(Collectors.toList())
.contains(experienceLevel.toUpperCase());
if (isValid) {
return Seniority.valueOf(experienceLevel.toUpperCase());
} else {
return null;
}
Is it possible to do all these actions by using stream only?
You can also use only valueOf()
If the value doesn't exist you can catch it with IllegalArgumentException.
boolean isValid = true;
try {
Seniority.valueOf(experienceLevel.toUpperCase());
} catch (IllegalArgumentException e) {
isValid = false;
}
Is it possible to check if the given string matches one of enum-names
and then return that enum-element?
You can use the generic method listed below for any type of enum.
Method EnumSet.allOf() expects a Class<T> object (and T has to be an enum) and returns a set of enum-constants.
Use filter() operation to find the matching enum-element. In place toUpperCase() you can use equalsIgnoreCase() which more expressive in this situation.
Method findFirst() returns an optional object if the stream is empty (i.e. match was not found). If you are not comfortable with it, you can apply orEsle(null) to return a string from the method. But I encourage you to get familiar with the capacities of the Optional instead of treating null as a legal value everywhere.
for more information on the Optional type take a look at this tutorial
public static <T extends Enum<T>> Optional<T> findMatchingEnumName(Class<T> enumClass,
String target) {
return EnumSet.allOf(enumClass).stream()
.filter(element -> element.name().equalsIgnoreCase(target))
.findFirst();
}
main() - demo, built-in enum DayOfWeek is used as an example.
public static void main(String[] args) {
System.out.println(findMatchingEnumName(DayOfWeek.class, "saturday"));
}
Output
Optional[SATURDAY]
I want to make a generic method that determines whether the first parameter is null, and if it is the case returns the second which is the default, else returns the first.
Can I make this possible?
I don't know how to implement it properly.
public static <T> ifNull(Object parameter, Object default, Class<T> type) {
return type.cast(parameter == null ? default: parameter));
}
Note: this code doesn't work for real, it's just an example.
I think this link might be useful:
is there a Java equivalent to null coalescing operator (??) in C#?
public static <T> T coalesce(T one, T two) {
return one != null ? one : two; }
or
public static <T> T coalesce(T... params) {
for (T param : params)
if (param != null)
return param;
return null; }
You can use something like this,
public static <T> T getValOrDefault(T value, T defaultValue) {
return value != null ? value : defaultValue;
}
I am not 100 % sure, but i think you want something like that:
public static <T> T ifNull(T parameter, T defaultValue) {
return parameter == null ? defaultValue: parameter;
}
If you are receiving two nullable objects of Object type and want to type-cast them dynamically to the given type by passing an in instance of Class<T> to your method, I think you were intending to achieve this:
public static <T> Optional<T> ifNull(Object first, Object second, Class<T> type) {
return Optional.ofNullable(type.cast(first))
.or(() -> Optional.ofNullable(type.cast(second)));
}
Class<T> object represents a class or interface
Method cast() will cast the given object to a particular type T, if it's the object is assignable to that type, otherwise a ClassCastException will be thrown. Note that compiler will not issue warnings for such way of downcasting (which is always potentially unsafe).
Optional is a special container-object introduced with Java 8 in order to be used a return type in cases when the resulting value could be null. Optional object might either contain a value or be empty, but it would never be null (if you are following good practices and not using optional as a field, method parameter and not storing it anywhere)
Optional.ofNullable() creates optional object containing the given value, if it's non-null, otherwise returns an empty optional.
Method or() will substitute the current optional object, if it is empty, with the provided optional.
The result of method execution will be the following:
Optional[first] --(first == null)--> Optional[second] --(second == null)--> empty optional
Note:
In order to declare a generic method you have to place a generic type parameter like <T> or wild card <? extends Number> between modifiers and return type or keyword void (in the method above <T> is ageneric type parameter and Optional<T> is a return type).
default is a keyword in Java.
TL;DR
What is the best (i.e. most compact/readable) way of transforming a Guava Optional, using a function that might return null? (So that in that case, we should get an Optional.absent(), instead of an NPE.)
Bonus question: is there an advantage, in the Guava way, namely to throw NPE, if the transformer function returns null? (Instead of converting it to Optional.absent(), like in case of Java 8 Optionals.) Or is it just a shortcoming of the design?
Problem
As per the documentation of Guava Optional.transform:
Comparison to java.util.Optional: this method is similar to Java 8's
Optional.map, except when function returns null. In this case this
method throws an exception, whereas the Java 8 method returns
Optional.absent().
Example
The following function is common to both examples:
public String methodThatMighReturnNull(boolean returnNull, Integer input) {
return returnNull ? null : String.valueOf(input);
}
With Java 8 this does not throw an NPE, but returns an empty Optional:
Optional<Integer> input = Optional.of(42);
Optional<String> result = input.map(new Function<Integer, String>() {
public String apply(Integer input) {
return methodThatMighReturnNull(true, input);
}
});
The following, similar code with Guava throws an NPE:
Optional<Integer> input = Optional.of(42);
Optional<String> result = input.transform(new Function<Integer, String>() {
public String apply(Integer input) {
return methodThatMighReturnNull(true, input);
}
});
Possible alternatives
I have found/considered some alternatives, but, as described below, all are problematic:
Wrap the return value into an Optional. Problem: too cumbersome, more difficult to read;
Optional<Integer> input = Optional.of(42);
Optional<String> result = input.transform(new Function<Integer, Optional<String>>() {
public Optional<String> apply(Integer input) {
return fromNullable(methodThatMighReturnNull(true, input));
}
}).get();
Use if/else, by checking ifPresent. Problem: kind of kills the point of Optional. (We could just use the reference and check against null instead.)
Optional<Integer> input = Optional.of(42);
Optional<String> result;
if (input.isPresent()) {
result = fromNullable(methodThatMighReturnNull(true, input.get()));
} else {
result = Optional.absent();
}
Just applying the function, and wrapping it in fromNullable. (As found on GitHub, where the same problem was seemingly already brought up.) Problem: this is slightly different, than the original example. In this case, methodThatMighReturnNull could end up receiving null, while in the original case this was impossible.
Optional<Integer> input = Optional.of(42);
Optional<String> result;
result = fromNullable(new Function<Integer, String>() {
public String apply(Integer input) {
return methodThatMighReturnNull(true, input);
}
}.apply(input.orNull()));
Apart from the alternatives you listed in your question, here are two other possibilities:
If you are on Java 8 or higher, starting from Guava 21.0, you have the Optional.toJavaUtil() instance method, which transforms your Guava Optional instance into a java.util.Optional one, and also the Optional.fromJavaUtil static method, which creates a Guava Optional instance from a java.util.Optional one.
You can use them to let java.util.Optional take a function that invokes your method in its Optional.map method, applying its own semantics (it won't throw NullPointerException if the function returns null, but an empty java.util.Optional instead). Then, if you need it, convert this mapped java.util.Optional back to a Guava Optional via the Optional.fromJavaUtil method.
Here's the code that shows this approach:
Optional<Integer> input = Optional.of(42);
java.util.Optional<String> temp = input.toJavaUtil()
.map(i -> methodThatMighReturnNull(true, i));
Optional<String> result = Optional.fromJavaUtil(temp);
If you are not in Java 8 or higher yet (or if you are but don't like the previous approach), I would go for a variant of your 2nd alternative. For this, I would implement a transformNullSafe method with the semantics you need:
public static <T, R> Optional<R> transformNullSafe(
Optional<T> optional,
Function<T, R> function) {
if (optional.isPresent()) {
return Optional.fromNullable(function.apply(optional.get()));
} else {
return Optional.absent();
}
}
Usage:
Optional<Integer> input = Optional.of(42);
Optional<String> result = transformNullSafe(
input,
new Function<Integer, String>() {
public String apply(Integer i) {
return methodThatMighReturnNull(true, i);
}
});
I am trying to find a clean and code-efficient way to convert Optional<Integer> to Optional<Long>. I am working in Java 7 with Guava.
So in one place in the code I have an optional integer created
Optional<Integer> optionalInt = Optional.fromNullable(someInt);
And in another area I need it as an optional long.
The nicest thing I could come up with is this:
Optional<Long> optionalLong = optionalInt.transform(new Function<Integer, Long>() {
#Override
public Long apply(Integer inputInt) {
if (inputInt != null)
return inputInt.longValue();
else
return null;
}
});
But this is cumbersome, especially if you consider how easy it was to cast the type when I was using primitive types.
Any good ideas out there?
TL;DR: In Java 7, No.
Sadly this is the best Java 7 has to offer in terms of support for functions.
I would just say that transform will never be called with null so you can do:
Optional<Long> optionalLong = optionalInt.transform(new Function<Integer, Long>() {
#Override
public Long apply(Integer inputInt) {
return inputInt.longValue();
}
});
From the documentation:
If the instance is present, it is transformed with the given
Function; otherwise, absent() is returned. If the function returns
null, a NullPointerException is thrown.
So never return null from a Function passed to transform.
If you reuse this a lot, then you could use the enum singleton pattern:
public enum IntToLong implements Function<Integer, Long> {
INSTANCE;
#Override
public Long apply(Integer input) {
return input.longValue();
}
}
Then:
optionalInt.transform(IntToLong.INSTANCE);
This obviously reduces the code at the call site at the expense of having extra classes in the code base - something I wouldn't be too worried about.
close to the cast:
Optional<Long> optionalLong = Optional.fromNullable(optionalInt.isPresent() ?
optionalInt.get().longValue() : null);
basically this avoids the overhead of invoking transform. Invoking isPresent could be simplified to checking the value for null directly.
What's the difference between these two methods: Optional.flatMap() and Optional.map()?
An example would be appreciated.
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.
They both take a function from the type of the optional to something.
map() applies the function "as is" on the optional you have:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
What happens if your function is a function from T -> Optional<U>?
Your result is now an Optional<Optional<U>>!
That's what flatMap() is about: if your function already returns an Optional, flatMap() is a bit smarter and doesn't double wrap it, returning Optional<U>.
It's the composition of two functional idioms: map and flatten.
Okay. You only need to use 'flatMap' when you're facing nested Optionals. Here's the example.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
Like Stream, Optional#map will return a value wrapped by a Optional. That's why we get a nested Optional -- Optional<Optional<Insurance>. And at ②, we want to map it as an Insurance instance, that's how the tragedy happened.
The root is nested Optionals. If we can get the core value regardless the shells, we'll get it done. That's what flatMap does.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
In the end, I stronly recommed the Java 8 In Action to you if you'd like to study Java8 Systematicly.
Note:- below is the illustration of map and flatmap function, otherwise Optional is primarily designed to be used as a return type only.
As you already may know Optional is a kind of container which may or may not contain a single object, so it can be used wherever you anticipate a null value(You may never see NPE if use Optional properly). For example if you have a method which expects a person object which may be nullable you may want to write the method something like this:
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
Here you have returned a String type which is automatically wrapped in an Optional type.
If person class looked like this, i.e. phone is also Optional
class Person{
private Optional<String> phone;
//setter,getter
}
In this case invoking map function will wrap the returned value in Optional and yield something like:
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS;
Never call get method (if you need to) on an Optional without checking it with isPresent() unless you can't live without NullPointerExceptions.
What helped me was a look at the source code of the two functions.
Map - wraps the result in an Optional.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
flatMap - returns the 'raw' object
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
Optional.map():
Takes every element and if the value exists, it is passed to the function:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Now added has one of three values: true or false wrapped into an Optional , if optionalValue was present, or an empty Optional otherwise.
If you don't need to process the result you can simply use ifPresent(), it doesn't have return value:
optionalValue.ifPresent(results::add);
Optional.flatMap():
Works similar to the same method of streams. Flattens out the stream of streams. With the difference that if the value is presented it is applied to function. Otherwise, an empty optional is returned.
You can use it for composing optional value functions calls.
Suppose we have methods:
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
Then you can compute the square root of the inverse, like:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
or, if you prefer:
Optional<Double> result = Optional.of(-4.0)
.flatMap(MyMath::inverse)
.flatMap(MyMath::squareRoot);
If either the inverse() or the squareRoot() returns Optional.empty(), the result is empty.
You can refer below link to understand in detail (best explanation which I could find):
https://www.programmergirl.com/java-8-map-flatmap-difference/
Both map and flatMap - accept Function. The return type of map() is a single value whereas flatMap is returning stream of values
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
They do the same thing.
The only difference is that, the lambda return's type is wrapped by Optional or not.
For normal usage, map is shorter than flatMap
Example:
package bj;
import java.util.Optional;
import static java.lang.System.out;
public class App {
public static void main(String[] args) {
out.println(Optional.of(10).map (x -> x * x));
out.println(Optional.of(10).flatMap(x -> Optional.of(x * x)));
out.println(Optional.of(10).map (x -> Optional.of(x * x).get()));
out.println(Optional.<Integer>empty().map (x -> x * x));
out.println(Optional.<Integer>empty().flatMap(x -> Optional.of(x * x)));
out.println(Optional.<Integer>empty().map (x -> Optional.of(x * x).get()));
}
}
Output:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty