当与 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/