Mapping a Nested Optional?

guava, java, java-8, lambda, option-type

Solution

I'm not really sure what you want, but you can rewrite your code like this:

RussianNestingDoll doll  = RussianNestingDoll.get(RussianNestingDoll.get(RussianNestingDoll.get()));

String content = doll.getInnerDoll()
                 .flatMap(d -> d.getInnerDoll())
                 .map(d -> d.get().toString())
                 .orElse("empty");
System.out.println(content);

In case you want to use the doll afterwards:

Optional<RussianNestingDoll> thirdDoll = doll.getInnerDoll()
                 .flatMap(d -> d.getInnerDoll());

if (thirdDoll.isPresent()) {
  System.out.println(thirdDoll.get());
}
else {                 
  System.out.println("empty");
}

Problem

I'm kind of running into a tedious issue with the Java 8 "Optional" container. I cannot map an Optional to "bubble up" another optional. Let's say I have a RussianNestingDoll class ``` public class NestedOptionalTest { public static void main(String[] args) { RussianNestingDoll doll = RussianNestingDoll.createInstance(RussianNestingDoll.createInstance(RussianNestingDoll.createInstance())); Optional<Optional<RussianNestingDoll>> thirdDollContents = doll.getInnerDoll().map(d -> d.getInnerDoll()); if (thirdDollContents.isPresent() && thirdDollContents.get().isPresent()) { System.out.println(thirdDollContents.get().get()); } else { System.out.println("empty"); } } private static final class RussianNestingDoll { private final Optional<RussianNestingDoll> innerDoll; public Optional<RussianNestingDoll> getInnerDoll() { return innerDoll; } private RussianNestingDoll(Optional<RussianNestingDoll> innerDoll) { this.innerDoll = innerDoll; } public static RussianNestingDoll createInstance() { return new RussianNestingDoll(Optional.empty()); } public static RussianNestingDoll createInstance(RussianNestingDoll innerDoll) { return new RussianNestingDoll(Optional.of(innerDoll)); } } } ``` It would be nice to not have to use nested optionals, and instead just have the optional "bubble up". That way I can call "isPresent()" and "get()" just once, rather than calling them both twice. Is there a way I can accomplish this?

Original source