簡體   English   中英

Java Streams with Optional 轉換的工作原理

[英]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 optCarOptional<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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM