5

I have this Java 8 code:

public Optional<User> getUser(String id) {
    Optional<User> userFromCache = cache.getUser(id);
    if (userFromCache.isPresent()) {
        return userFromCache;
    }
    return repository.getUser(id);
}

It works fine but I'm wondering how can I chain the call to not to use if. I have tried with orElseGet but it doesn't allow to return another Optional<User> but a User.

I want something like this:

Optional<User> userFromCache = cache.getUser(id)
    .orElseGet(() -> repository.getUser(id));
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Héctor
  • 24,444
  • 35
  • 132
  • 243
  • 3
    See here: https://stackoverflow.com/questions/28818506/optional-orelse-optional-in-java. There are answers for both JDK 8 and 9. See the answer by @Misha, here: https://stackoverflow.com/a/28821352. – Druckles Dec 17 '18 at 15:11
  • This really should be closed as a duplicate but I have no more flags .^. – Druckles Dec 17 '18 at 15:19
  • @Druckles Hmm, agreed. – Naman Dec 17 '18 at 15:20

3 Answers3

11

Since Java 9, there is Optional.or. It accepts a supplier for another Optional.

return cache.getUser(id).or(() -> repository.getUser(id));
Michael
  • 41,989
  • 11
  • 82
  • 128
khelwood
  • 55,782
  • 14
  • 81
  • 108
6

You can create an optional based on a nullable value from other optionals:

public Optional<User> getUser(String id) {
    return Optional.ofNullable(
        cache.getUser(id).orElseGet(
            () -> repository.getUser(id).orElse(null)
        )
    );
}

But your current solution is clearly more readable.

Michael
  • 41,989
  • 11
  • 82
  • 128
ernest_k
  • 44,416
  • 5
  • 53
  • 99
2

You can still use ?:

return (userFromCache.isPresent()) ? userFromCache : repository.getUser(id);

It's obviously an if in disguise but so is any other solution.

Erwin Smout
  • 18,113
  • 4
  • 33
  • 52