Java Streams with Optional 转换的工作原理

标签 java java-8 functional-programming java-stream optional

当与 map() 和 flatMap() 一起使用时,我无法理解 optional 和流的概念。

我理解这个代码:

public String getCarInsurance(Optional<Person> optPerson) {
    return optPerson.flatMap(Person::getCar) //Returns Optional<Car>
            .flatMap(Car::getInsurance) //Returns Optional<Insurance>, .map would give Optional<Optional<Insurance>>
            .map(Insurance::getName) //no need for flatmap because getName returns String, not Optional<String>
            .orElse("UNKNOWN"); //returns value or Unknown
}

但是,我无法理解这段代码:
 public Set<String> getCarInsuranceNames(List<Person> persons) {
        return persons.stream()
                .map(Person::getCar) //Convert the list of persons into Stream Optional<Car> 
                .map(optCar -> optCar.flatMap(Car::getInsurance)) //I don't understand this line
                .map(optIns -> optIns.map(Insurance::getName))
                .flatMap(Optional::stream)
                .collect(toSet());
    }

编辑:

为什么在这种情况下我们需要 .map(optCar -> optCar.flatMap(Car::getInsurance)) , 得到 Stream Optional<Insurance> ?但是在第一个代码中 .map(Car::getInsurance)足以得到Optional<Insurance> .

我明白我们为什么需要 .flatmap而不是 .map在第一个代码中,但我无法理解第二个代码中的 Stream 管道。

在第二个代码中 .map(Person::getCar)返回 Stream Optional<Car>然后我们使用 .map(optCar -> optCar.flatMap(Car::getInsurance))>获取 Stream Optional<Insurance> .为什么不.flatmap(Car::getInsurance)联系我们 Stream Optional<Insurance> ?这是我不明白的。

编辑:如果需要,下面的域类。
public class Insurance {
    public String getName() {
        return name;
    }   
}

public class Car {
    Optional<String> name;
        public Optional<String> getName() {
            return name;
        }

        public class Person {
            Optional<Car> car;
            public Optional<Car> getCar(){
                return car;
            }
        }

最佳答案

如果您可以保持两个代码段相同,这将有助于您理解

public String getCarInsurance(Optional<Person> optPerson) {
    return optPerson.flatMap(Person::getCar) //Returns Optional<Car>
            .flatMap(Car::getInsurance) //Returns Optional<Insurance>, .map would give Optional<Optional<Insurance>>
            .map(Insurance::getName) //no need for flatmap because getName returns String, not Optional<String>
            .orElse("UNKNOWN"); //returns value or Unknown
}

public Set<String> getCarInsuranceNames(List<Person> persons) {
    return persons.stream()
            .map(person -> person.getCar() // chained in a similar manner as above
                    .flatMap(Car::getInsurance)
                    .map(Insurance::getName))
            .flatMap(Optional::stream)
            .collect(Collectors.toSet());
}

或者更清晰,如果您可以改进 API 的现有契约(Contract)以
public Optional<String> getCarInsurance(Person person) {
    return person.getCar() //Returns Optional<Car>
            .flatMap(Car::getInsurance) //Returns Optional<Insurance>, .map would give Optional<Optional<Insurance>>
            .map(Insurance::getName); //no need for flatmap because getName returns String, not Optional<String>
}

public Set<String> getCarInsuranceNames(List<Person> persons) {
    return persons.stream()
            .flatMap(person -> getCarInsurance(person).stream())
            .collect(Collectors.toSet());
}

关于Java Streams with Optional 转换的工作原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60890550/

相关文章:

java - 使用 Java 8 谓词查找 "most"正确值

java - 无状态 EJB 中的静态成员与实例成员

JAVA。一个打印骰子的 GUI

java - 枚举的通用过滤器

java - 如何从 Java 8 中的 getAnnotatedParameterTypes() 获取泛型类型信息?

c++ - C++0x 中的纯/常量函数

java - 尽管保留了所有内容,但无法使用 log4j 生成日志文件

java - 我怎样才能在 Java 中获得第 5 个根?

JavaFx ImageView 不会在绑定(bind)到 VBox 的 fitWidthProperty 上调整大小

functional-programming - 使用 Ada 子类型等函数语言定义自然数