了解了Optional的map方法与stream的map()的区别,我们再来看一下Optional的flatMap方法与Optional的map方法的区别。
我们先来看一个demo:
@Data
public class OptPerson {
private String name;
private Optional<OptCar> optCar;
}
@Data
public class OptCar {
private String carName;
private OptCarBrand optCarBrand;
}
@Data
public class OptCarBrand {
private String brandName;
}
public class OptFlatMap {
public static void main(String[] args) {
OptPerson person = new OptPerson();
Optional<OptPerson> optPerson = Optional.of(person);
optPerson.map(OptPerson::getOptCar)
.map(OptCar::getOptCarBrand)
.map(OptCarBrand::getBrandName);
}
}
测试代码main函数其实是报错的,无法通过编译:
optPerson.map(OptPerson::getOptCar)
.map(OptCar::getOptCarBrand)
.map(OptCarBrand::getBrandName);
原因在于getOptCar获取的是Optional,optPerson.map(OptPerson::getOptCar)获取到的就是Optional>
如果要消除这种编译错误,可以在optPerson.map(OptPerson::getOptCar)后使用get()方法,如下:
optPerson.map(OptPerson::getOptCar).get()
.map(OptCar::getOptCarBrand)
.map(OptCarBrand::getBrandName);
但是这种用法就没有将Optonal自动消除空指针的优势发挥出来,按照上面的代码添加get()方法执行后,代码报错:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at com.itzhimei.base.lambda.option.OptFlatMap.main(OptFlatMap.java:11)
那么一个好的解决方案就是使用flatMap方法,作用和stream的flatMap是一样的,也是流的扁平化。应用到上面的例子,就是在运算过程中,将Optional>结果转换成Optional。
我们看demo:
public class OptFlatMap {
public static void main(String[] args) {
OptPerson person = new OptPerson();
person.setName("IT之美");
Optional<OptPerson> optPerson = Optional.of(person);
person.setOptCar(Optional.empty());
System.out.println(optPerson.flatMap(OptPerson::getOptCar)
.map(OptCar::getOptCarBrand)
.map(OptCarBrand::getBrandName));
}
}
/* 输出
Optional.empty
*/
使用flatMap的注意:
1、你要明确知道,哪个位置需要进行流的扁平化,像我们上面的代码,只有car是需要flatMap处理的,不是Optional类型的依然用map来做类型转换。
2、使用flatMap,一定要注意对变化化处理的这一层需要实例化,也就是person中的car必须要创建,否则也是空指针,car哪怕是使用Optonal.empty()也是可以的,但是不能不创建。