Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Java: How to reduce Optionals of different types?

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

  1. The first one returns an Optional of type User
  2. 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.

>Solution :

If you have a fixed number of optionals, use a chain of flatMaps, 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))))));
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading