Optional.flatMap 和 Optional.map 有什么区别?
What is the difference between Optional.flatMap and Optional.map?
Optional.flatMap()
和 Optional.map()
这两种方法有什么区别?
一个例子将不胜感激。
他们都从可选的类型中获取一个函数。
map()
将函数“按原样”应用于您的可选选项:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
如果你的函数是来自 T -> Optional<U>
的函数会怎样?
您的结果现在是 Optional<Optional<U>>
!
这就是 flatMap()
的意义所在:如果您的函数已经 returns 一个 Optional
,flatMap()
会更聪明一点并且不会将其双重包装,返回 Optional<U>
。
它是两个功能习语的组合:map
和 flatten
。
如果函数 returns 是您需要的对象,则使用 map
,如果函数 returns 和 Optional
,则使用 flatMap
。例如:
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);
}
两个打印语句打印相同的内容。
注意:- 下面是 map 和 flatmap 函数的说明,否则 Optional 主要设计为仅用作 return 类型。
你可能已经知道 Optional 是一种容器,它可能包含也可能不包含单个对象,因此它可以在你预期为 null 值的任何地方使用(如果正确使用 Optional,你可能永远不会看到 NPE)。例如,如果您有一个方法需要一个可以为 null 的 person 对象,您可能希望编写这样的方法:
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
}
在这里您return编辑了一个字符串类型,它自动包装在可选类型中。
如果 class 看起来像这样,即 phone 也是可选的
class Person{
private Optional<String> phone;
//setter,getter
}
在这种情况下,调用 map 函数会将 returned 值包装在 Optional 中,并产生如下内容:
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;
永远不要在 Optional 上调用 get 方法(如果需要)而不用 isPresent() 检查它,除非你不能没有 NullPointerExceptions。
对我有帮助的是查看这两个函数的源代码。
Map - 将结果包装在 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 'raw' 对象
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()
:
获取每个元素,如果该值存在,则将其传递给函数:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
现在 added 具有三个值之一:true
或 false
包装到 Optional ,如果 optionalValue
存在,或者 空 Optional 否则
如果您不需要处理结果,您可以简单地使用 ifPresent()
,它没有 return 值:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:
工作原理与流的相同方法类似。展平溪流。不同之处在于,如果值被呈现,它将应用于功能。否则,一个空的可选是 returned.
您可以使用它来组合可选的值函数调用。
假设我们有方法:
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));
}
然后你可以计算逆的平方根,比如:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
或者,如果您愿意:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
如果inverse()
或squareRoot()
returns Optional.empty()
,则结果为空。
好的。你 只需要在你面对嵌套的 Optionals 时使用 'flatMap'。这是例子。
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); // ②
}
}
与 Stream 一样,Optional#map 将 return 一个由 Optional 包装的值。这就是为什么我们得到一个嵌套的 Optional -- Optional<Optional<Insurance>
。而在②处,我们想把它映射成一个Insurance实例,悲剧就这样发生了。
根是嵌套的 Optionals。如果我们能够不顾外壳获得核心价值,我们就会完成它。这就是 flatMap 所做的。
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
最后,如果你想系统地学习Java8,我强烈推荐Java 8 In Action给你。
你可以参考下面link来详细了解(我能找到的最好的解释):
https://www.programmergirl.com/java-8-map-flatmap-difference/
map 和 flatMap 都接受函数。 return 类型的 map() 是单个值,而 flatMap 是 returning 值流
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
他们做同样的事情。
唯一的区别是,lambda
return的类型被wrappedOptional
与否。
对于正常使用,map
比 flatMap
短
示例:
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()));
}
}
输出:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty
Optional.flatMap()
和 Optional.map()
这两种方法有什么区别?
一个例子将不胜感激。
他们都从可选的类型中获取一个函数。
map()
将函数“按原样”应用于您的可选选项:
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
如果你的函数是来自 T -> Optional<U>
的函数会怎样?
您的结果现在是 Optional<Optional<U>>
!
这就是 flatMap()
的意义所在:如果您的函数已经 returns 一个 Optional
,flatMap()
会更聪明一点并且不会将其双重包装,返回 Optional<U>
。
它是两个功能习语的组合:map
和 flatten
。
如果函数 returns 是您需要的对象,则使用 map
,如果函数 returns 和 Optional
,则使用 flatMap
。例如:
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);
}
两个打印语句打印相同的内容。
注意:- 下面是 map 和 flatmap 函数的说明,否则 Optional 主要设计为仅用作 return 类型。
你可能已经知道 Optional 是一种容器,它可能包含也可能不包含单个对象,因此它可以在你预期为 null 值的任何地方使用(如果正确使用 Optional,你可能永远不会看到 NPE)。例如,如果您有一个方法需要一个可以为 null 的 person 对象,您可能希望编写这样的方法:
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
}
在这里您return编辑了一个字符串类型,它自动包装在可选类型中。
如果 class 看起来像这样,即 phone 也是可选的
class Person{
private Optional<String> phone;
//setter,getter
}
在这种情况下,调用 map 函数会将 returned 值包装在 Optional 中,并产生如下内容:
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; 永远不要在 Optional 上调用 get 方法(如果需要)而不用 isPresent() 检查它,除非你不能没有 NullPointerExceptions。
对我有帮助的是查看这两个函数的源代码。
Map - 将结果包装在 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 'raw' 对象
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()
:
获取每个元素,如果该值存在,则将其传递给函数:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
现在 added 具有三个值之一:true
或 false
包装到 Optional ,如果 optionalValue
存在,或者 空 Optional 否则
如果您不需要处理结果,您可以简单地使用 ifPresent()
,它没有 return 值:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:
工作原理与流的相同方法类似。展平溪流。不同之处在于,如果值被呈现,它将应用于功能。否则,一个空的可选是 returned.
您可以使用它来组合可选的值函数调用。
假设我们有方法:
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));
}
然后你可以计算逆的平方根,比如:
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
或者,如果您愿意:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
如果inverse()
或squareRoot()
returns Optional.empty()
,则结果为空。
好的。你 只需要在你面对嵌套的 Optionals 时使用 'flatMap'。这是例子。
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); // ②
}
}
与 Stream 一样,Optional#map 将 return 一个由 Optional 包装的值。这就是为什么我们得到一个嵌套的 Optional -- Optional<Optional<Insurance>
。而在②处,我们想把它映射成一个Insurance实例,悲剧就这样发生了。
根是嵌套的 Optionals。如果我们能够不顾外壳获得核心价值,我们就会完成它。这就是 flatMap 所做的。
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
最后,如果你想系统地学习Java8,我强烈推荐Java 8 In Action给你。
你可以参考下面link来详细了解(我能找到的最好的解释):
https://www.programmergirl.com/java-8-map-flatmap-difference/
map 和 flatMap 都接受函数。 return 类型的 map() 是单个值,而 flatMap 是 returning 值流
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
他们做同样的事情。
唯一的区别是,lambda
return的类型被wrappedOptional
与否。
对于正常使用,map
比 flatMap
示例:
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()));
}
}
输出:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty