option . flatmap()和option .map()这两个方法之间有什么区别?

请举例说明。


当前回答

他们做同样的事情。

唯一的区别是,lambda返回的类型被Optional或非Optional包装。

正常使用时,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

其他回答

对我有帮助的是查看这两个函数的源代码。

映射将结果包装在可选对象中。

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 -返回'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
    }
}

他们做同样的事情。

唯一的区别是,lambda返回的类型被Optional或非Optional包装。

正常使用时,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

注意:-下面是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类型中。

如果person类看起来像这样,即phone也是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; 永远不要在一个Optional对象上调用get方法(如果需要的话),而不使用isPresent()检查它,除非你不能没有NullPointerExceptions。

好的。你只需要使用'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>。在②,我们想把它映射成一个保险实例,这就是悲剧发生的方式。 根是嵌套的optional。如果我们能得到核心价值,不管外壳如何,我们就能完成它。这就是flatMap所做的。

public Optional<String> getCarInsuranceName(Person person) {
    return person.getOptionalCar()
                 .flatMap(Car::getOptionalInsurance)
                 .map(Insurance::getName);
}

最后,如果你想系统地学习Java8,我强烈推荐《Java8 In Action》。

它们都从可选类型中取一个函数。

Map()在你拥有的可选对象上应用函数"as is":

if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));

如果你的函数是T ->可选<U>的函数会发生什么? 你的结果现在是一个Optional<Optional<U>>!

这就是flatMap()的意义所在:如果你的函数已经返回了一个Optional, flatMap()会更聪明一点,不会将它双换行,返回Optional<U>。

它是map和flatten这两个功能习语的组合。