2

I would like to convert Optional<CompletableFuture<T>> to CompletableFuture<Optional<T>>. Is there more idiomatic way not using Optional.get()?

Optional<CompletableFuture<T>> opt = Optional.empty();
CompletableFuture<Optional<T>> fut =
        opt.isPresent() ?
                opt.get().thenApply(Optional::of) :
                CompletableFuture.completedFuture(Optional.empty());
John Beff
  • 133
  • 2
  • 5
  • @tunaki, honestly, the answers given at [If not null - java 8 style](http://stackoverflow.com/questions/32306530/if-not-null-java-8-style) yet are far from the idiomatic way of using Optional. – Max Plevako Oct 31 '15 at 10:10
  • @MaximPlevako The OP is asking exactly for the `ifPresentOrElse` method that the answer given in the dupe talks about. If it's better or not than a if/else or ternary, this is opinion-based IMO. – Tunaki Oct 31 '15 at 10:16
  • @tunaki, no, the OP asks exactly about *more idiomatic* way that does not use `Optional.get()`. And this question has such pure idiomatic solution in contrast to [If not null - java 8 style](http://stackoverflow.com/questions/32306530/if-not-null-java-8-style). – Max Plevako Oct 31 '15 at 10:19
  • @MaximPlevako [this](http://stackoverflow.com/q/23773024/1743880) question would also qualify as a dupe target. – Tunaki Oct 31 '15 at 10:25
  • @tunaki, [this one](http://stackoverflow.com/questions/23773024/functional-style-of-java-8s-optional-ifpresent-and-if-not-present) is indeed valid. I see an approaching answer there. – Max Plevako Oct 31 '15 at 10:29
  • But, @tunaki, I cannot agree that a question if an `Optional` is better than if/else is opinion-based. Ultimately, one of the aims of `Optional` was to get rid of excessive conditionals. – Max Plevako Oct 31 '15 at 10:34
  • The solution to this question is `fut = opt.map(f -> f.thenApply(Optional::of)).orElseGet(() -> CompletableFuture.completedFuture(Optional.empty()))`. @Tunaki It does not need a `ifPresentOrElse` or `ifPresent`/`ifNotPresent`. An alternative solution would be `opt.orElseGet(() -> CompletableFuture.completedFuture(null)).thenApply(Optional::ofNullable)` with slightly different behavior as it does not fail if the initial future returns `null`. – Didier L Dec 02 '16 at 16:33
  • @Tunaki I think the dupe should be changed at least, however in the context of `CompletableFuture`, I'm not sure most people would be able to reach the solution based on it. This is a particular case in which the OP wanted to swap the inner and outer types, not really do an if/else. – Didier L Dec 02 '16 at 17:26

1 Answers1

4

You can do the conversion with a combination of map() and orElseGet():

CompletableFuture<Optional<T>> fut = opt.map(f -> f.thenApply(Optional::of))
    // now you have an Optional<CompletableFuture<Optional<T>>>
    // just get rid of the outer Optional and you have the desired result:
    .orElseGet(() -> CompletableFuture.completedFuture(Optional.empty()))

Alternatively, you can also do the following:

opt.orElseGet(() -> CompletableFuture.completedFuture(null))
   .thenApply(Optional:‌​:ofNullable)

the main difference being that if the initial CompletableFuture returns null, this one will not throw a NullPointerException.

Didier L
  • 18,905
  • 10
  • 61
  • 103