[英]Java Streams with Optional how transforming works
當與 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 的現有合同以
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());
}
這樣做是為了避免嵌套Optional
。 optCar
是Optional<Car>
類型。 如果我們調用map(optCar -> optCar.map(Car::getInsurance))
而不是map(optCar -> optCar.flatMap(Car::getInsurance))
,那么我們最終會得到Stream<Optional<Optional<Insurance>>>
.
但是嵌套 optional 沒有多大意義,如果我們有Optional<A>
類型的optA
並且有一個方法A#getB
,它返回Optional<B>
,那么我們可以通過調用optA.flatMap(A::getB)
,這將導致Optional<B>
:
Optional<B> optB = optA.flatMap(A::getB);
Optional<Optional<B>> optOptB = optA.map(A::getB); // don't do that
optA.flatMap(A::getB)
直觀地工作 - 如果optA
為空或optA
有值,但optA.getB()
為空,則flatMap
的結果將是空的Optional<B>
。 僅當optA
有值且optA.getB()
不為空時,結果才不會為空。
在第一個片段中flatMap
就足夠了,因為它是對Optional
的操作,而在第二個片段中我們是對Stream
操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.