I know it's possible to merge Optionals of the same type.
public static void main(String[] args) {
var foo = Stream.of(Optional.of("a"), Optional.of("b"))
.flatMap(Optional::stream)
.reduce((a, b) -> a "-" b)
.orElse(null);
System.out.println(foo); // prints "a-b"
}
However I'm struggling to merge Optionals of different types.
public class Example {
record A(){}
record B(){}
record C(A a, B b){}
public static void main(String[] args) {
var foo = Stream.of(Optional.of(new A()), Optional.of(new B()))
.flatMap(Optional::stream)
.reduce((a, b) -> new C(a, b))
.orElse(null);
System.out.println(foo);
}
}
That does not work and I'm getting the error.
Type mismatch: cannot convert from Example.C to capture#1-of ? extends Record
I tried different versions with type casting but no success so far. Any ideas?
Edit: adding some more information
This is obviously a trivial and very simple example. In real life I have two methods
- The first one returns an Optional of type
User
- The second one returns an Optional of Type
Animal
When both are successful / not empty I'd like to call a method myMethod(User user, Animal animal)
. So the question is basically about joining / merging two optionals and work with the enclosed values afterwards.
CodePudding user response:
If you have a fixed number of optionals, use a chain of flatMap
s, ending with another flatMap
or map
, in order to map all of them to Optional<AnotherType>
.
In the case of two optionals, this looks like:
Optional<A> aOpt = Optional.of(new A());
Optional<B> bOpt = Optional.of(new B());
Optional<C> c = aOpt.flatMap(a ->
bOpt.map(b ->
new C(a, b)));
You can generalise this to n optionals:
// opt1 to opt5 can all be different types of optionals
opt1.flatMap(a ->
opt2.flatMap(b ->
opt3.flatMap(c ->
opt4.flatMap(d ->
opt5.map(e -> // if f returns another optional, you'd use flatMap here too
f(a, b, c, d, e))))));