『浅读』Optional中flatMap的使用

625 阅读2分钟

Java核心技术 卷Ⅱ 原书第十版

原书中对flatMap作用的描述

假设你有一个可以产生Optional<T>对象的方法f,并且目标类型T具有一个可以产生Optional<U>对象的方法g。如果它们都是普通的方法,那么你可以通过调用s.f().g()来将它们组合起来。但是这种组合没法工作,因为s.f()的类型为Optional<T>,而不是T。
因此,需要调用:
Optional<U> result = s.f().flatMap(T::g);

对书中表述的理解

因为s.f()的类型为Optional<T>,而不是T。因此,需要调用.....
我从一开始读到这里,产生了歧义,以为想要调用目标类型的方法就需要使用flatMap方法;
转念一想,map方法就能实现啊!

flatMap方法的作用及与map的区别

flatMap方法是将映射方法取回的结果不再次使用Optional进行包装;
举例如下:

public class School{
    public String name;
    public Optional<Teacher> teacher;
    // getter setter ...
}
public class Teacher{
    public String name;
    public Optional<Classes> classes;
    // getter setter ...
}
public class Classes{
    public String name;
    public List<String>books; //课程使用的书籍
    // getter setter ...
}

如果给一个School对象,想要获取书籍列表怎么写呢?

public static List<String> getBookList(School school){
    return Optional.ofNullable(school)
            .map(School::getTeacher)
            .map(Teacher::getClasses)
            .map(Classes::getBooks)
            .orElseGet(Collections.emptyList())
}

但是仔细想一下,school中的teacher属性已经是Optional包装过后的了,使用map方法,会返回Optional<Optional<Teacher>>对象,显然不符合预期。
因此,可以使用flatMap解决,flatMap不会使用Optional包装映射的结果,但要求映射的结果需要是Optional包装过的。

public static List<String> getBookList(School school){
    return Optional.ofNullable(school)
            .flatMap(School::getTeacher)
            .flatMap(Teacher::getClasses)
            .map(Classes::getBooks)
            .orElseGet(Collections.emptyList())
总结
  • map方法会对映射返回的结果使用Optional进行包装,因此在返回非Optional包装类型时使用map方法。
  • flatMap方法对映射返回的结果不再使用Optional进行包装,但是映射返回的结果要求是Optional包装类型,此时使用flatMap方法。

如有错误,请大家指正!