Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping a Nested Optional?

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?

like image 516
tmn Avatar asked Feb 19 '15 17:02

tmn


People also ask

What does map do in optional?

The map method returns the result of the computation wrapped inside Optional. We then have to call an appropriate method on the returned Optional to retrieve its value. We can chain map and filter together to do something more powerful.

What exception is thrown by optional get when not nested?

Optional's get() method returns a value if it is present, otherwise it throws NoSuchElementException. You should avoid using get() method on your Optionals without first checking whether a value is present or not, because it throws an exception if the value is absent.

What is optional isPresent?

In Java, the Optional object is a container object that may or may not contain a value. Using the Optional object's isPresent method, we can replace the multiple null check. The Optional class is present in the java. util package.

What is the use of optional ()?

Core Java bootcamp program with Hands on practice Optional is a container object used to contain not-null objects. Optional object is used to represent null with absent value. This class has various utility methods to facilitate code to handle values as 'available' or 'not available' instead of checking null values.


2 Answers

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");
}
like image 95
a better oliver Avatar answered Oct 22 '22 01:10

a better oliver


Do you want to flatMap?

thirdDollContents
    .flatMap(Function.identity()) // un-nest, get back an Optional<RussianNestingDoll>
    .get() // or isPresent()

The flatMap will return an empty Optional if thirdDollContents is empty.

like image 37
Sotirios Delimanolis Avatar answered Oct 21 '22 23:10

Sotirios Delimanolis