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方法。
如有错误,请大家指正!