0

I have the following code and it works as expected:

Optional.ofNullable(testItem.getId())
                .map(testItemRepository::get)
                .orElseThrow(() -> new TestException(ReturnCode.UNKNOWN_ID))
                .orElseThrow(() -> new TestException(ReturnCode.UNKNOWN_ID));

I would like to know if there is a way to just have one orElseThrow-Part or do it less redundant ?

Shorty123
  • 539
  • 1
  • 7
  • 26
  • 5
    It's hard to tell because it's not clear what `testItemRepository::get` returns (does it return an `Option`?). Try using `flatMap` instead of `map` and remove the last `orElseThrow` line. – Jesper Nov 16 '20 at 08:04
  • Yes it returns an optional. thx for the quick answer. – Shorty123 Nov 16 '20 at 08:05

2 Answers2

3

Use Optional#flatMap method that flattens the Optional structure as long the call of the method testItemRepositoryget results in Optional.

 Optional.ofNullable(testItem.getId())
            .flatMap(testItemRepository::get)
            .orElseThrow(() -> new TestException(ReturnCode.UNKNOWN_ID));

I.e. from Optional<Optional<MyObject>> to Optional<MyObect>.

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
3

It seems to be the case that testItemRepository::get returns another Optional<Something>. In that case, you should not use map. Using map will get you a nested optional - Optional<Optional<Something>>, which as you have found out, is not nice to work with. flatMap is made for exactly this situation:

Optional.ofNullable(testItem.getId())
            .flatMap(testItemRepository::get)
            .orElseThrow(() -> new TestException(ReturnCode.UNKNOWN_ID));

flatMap turns an Optional<A> to an Optional<B>, given a Function<A, Optional<B>>.

Sweeper
  • 213,210
  • 22
  • 193
  • 313