Lambda从入门到精通之二十七 Optional对象的flatMap方法的使用方法

了解了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()也是可以的,但是不能不创建。