这两种方法有什么区别:Optional.flatMap()
和Optional.map()
?
一个例子将不胜感激。
答案 0 :(得分:116)
如果函数返回您需要的对象,则使用map
;如果函数返回flatMap
,则使用Optional
。例如:
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);
}
两个印刷语句都打印相同的内容。
答案 1 :(得分:46)
他们都从可选的类型中获取函数。
Optional<Optional<U>>
在您拥有的可选项上应用“ 原样 ”功能:
flatMap()
如果您的功能是Optional
的功能,会发生什么?
您的结果现在是flatMap()
!
这就是Optional<U>
的含义:如果你的函数已经返回map
,flatten
有点聪明并且没有双重包裹它,那么返回var photos = [];
var ImgUrl="images/Thomas.jpg";
photos[0] = new ContactField('url', ImgUrl,true);
contact.photos = photos;
。
这是两个功能习语的组成:{{1}}和{{1}}。
答案 2 :(得分:6)
注意: - 下面是map和flatmap函数的图示,否则Optional主要设计为仅用作返回类型。
您可能已经知道Optional是一种容器,可能包含也可能不包含单个对象,因此可以在预期空值的任何地方使用它(如果正确使用Optional,您可能永远不会看到NPE)。例如,如果你有一个方法需要一个可以为空的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
}
在这里,您返回了一个String类型,它自动包装在Optional类型中。
如果人员班级看起来像这样,即电话也是可选的
class Person{
private Optional<String> phone;
//setter,getter
}
在这种情况下,调用map函数会将返回的值包装在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; 永远不要使用isPresent()调用get方法(如果需要)而不用isPresent()进行检查,除非你不能在没有NullPointerExceptions的情况下生活。
答案 3 :(得分:5)
帮助我的是看两个函数的源代码。
地图 - 将结果包装在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 - 返回'原始'对象
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
}
}
答案 4 :(得分:3)
Optional.map()
:获取每个元素,如果该值存在,则将其传递给函数:
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
现在已添加具有以下三个值之一:true
或false
包装在 可选 中,如果{ {1}}存在,否则为 空可选 。
如果您不需要处理结果,则只需使用optionalValue
,它就没有返回值:
ifPresent()
optionalValue.ifPresent(results::add);
:工作原理类似于相同的流方法。展平流。不同之处在于,如果显示值,则将其应用于功能。否则,将返回一个空的可选内容。
您可以使用它来构成可选的值函数调用。
假设我们有方法:
Optional.flatMap()
然后,您可以计算逆的平方根,例如:
Double result = inverse(-4.0).flatMap(MyMath :: squareRoot);
或者,如果您愿意:
双重结果=可选.of(-4.0).flatMap(MyMath :: inverse).flatMap(MyMath :: squareRoot);
如果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));
}
或inverse()
返回squareRoot()
,则结果为空。
答案 5 :(得分:3)
好的。面对嵌套的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将返回一个由Optional包装的值。这就是为什么我们得到嵌套的Optional-Optional<Optional<Insurance>
。在②,我们希望将其映射为保险实例,这就是悲剧的发生方式。
根是嵌套的Optionals。如果我们能获得核心价值而不管外壳如何,那么我们就完成它。这就是flatMap的功能。
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
最后,如果您想系统地学习Java8,我会向您推荐 Java 8 In Action 。
答案 6 :(得分:0)
您可以参考以下链接详细了解(我能找到的最佳解释):
https://www.programmergirl.com/java-8-map-flatmap-difference/
map 和 flatMap - 都接受函数。 map() 的返回类型是单个值,而 flatMap 返回值流
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)