I can't understand the concept of optional and streams when used with map() vs flatMap().
I understand this code :
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
}
But, I can't understand this code :
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());
}
edit:
Why in this case we need .map(optCar -> optCar.flatMap(Car::getInsurance)), to get Stream Optional<Insurance> ? But in first code .map(Car::getInsurance) was enough to get Optional<Insurance>.
I understand why we need .flatmap instead of .map in first code, but I can't understand the pipeline of Stream in second code.
In second code .map(Person::getCar) returns Stream Optional<Car> and then we use .map(optCar -> optCar.flatMap(Car::getInsurance))> to get Stream Optional<Insurance> . Why wouldn't .flatmap(Car::getInsurance) get us Stream Optional<Insurance> ? This what I fail to understand.
edit: Domain classes below if needed.
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;
}
}