66

I have two java.util.Optional instances and I want to get an Optional that either:

  • Has the value of the first Optional, if it has a value.
  • Has the value of the second Optional, if it has a value.
  • Is empty of neither Optional has a value.

Is there a straight-forward way to do that, i.e. is there already some API to do that?

The following expressions will do that, but I have to mention the first optional twice:

firstOptional.isPresent() ? firstOptional : secondOptional

This is exactly what com.google.common.base.Optional.or() does, but that method is not present in Java 8's API.


The accepted answer by aioobe lists a few alternative approaches to overcome this omission of the Optional API right where such a value has to be computed (which answers my question). I've now opted to add a utility function to my codebase:

public static <T> Optional<T> or(Optional<T> a, Optional<T> b) {
    if (a.isPresent())
        return a;
    else
        return b;
}
Feuermurmel
  • 9,490
  • 10
  • 60
  • 90
  • 2
    If you opt for using a utility function, I would recommend using a `Supplier>` for the second parameter to support short-circuiting if the first is present. – r0estir0bbe Apr 25 '17 at 12:22
  • @r0estir0bbe That would definitely be an option. I think both arguments were very cheap to calculate in the instance I was originally needing this. If it were after me, I'd be writing Haskell, where I wouldn't have to think about it. :) – Feuermurmel Apr 26 '17 at 07:33

5 Answers5

88

Java 9 and above:

firstOptional.or(() -> secondOptional);

Java 8 and below

If you want to avoid mentioning firstOptional twice, you'd probably have to go with something like

firstOptional.map(Optional::of).orElse(secondOptional);

or

Optional.ofNullable(firstOptional.orElse(secondOptional.orElse(null)));

But the most readable variant is probably to simply do

Optional<...> opt = firstOptional.isPresent()  ? firstOptional
                  : secondOptional.isPresent() ? secondOptional
                  : Optional.empty();

If someone stumbles across this question but has a list of optionals, I'd suggest something like

Optional<...> opt = optionals.stream()
                             .filter(Optional::isPresent)
                             .findFirst()
                             .orElse(Optional.empty());
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • Won't your third example return an Optional> since findFirst is operating on a Stream>? You want stream().filter(Optional::isPresent).map(o -> o.get()).findFirst() – everett1992 Jun 17 '15 at 16:34
  • 2
    I think it's worth mentioning, that the Java 8 equivalent of the Java 9 `Optional.or` is `firstOptional.map(Optional::of).orElseGet(()->secondOptional)`. It only evaluates `secondOptional` if `firstOptional` is empty. Behaving in analogy to the logical `||`. – wuerg Dec 19 '17 at 18:08
10

EDIT: I totally thought you were using Guava's Optional originally. I've updated my answer to supply both Guava and Java 8 syntax for their respective Optional classes.

Java 8 Optional

You can shorten it up to this:

firstOptional.orElse(secondOptional.orElse(EMPTY_VALUE))

I'm not sure what you meant in your third bullet by "empty". If you meant null then this'll do the trick:

firstOptional.orElse(secondOptional.orElse(null))

orElse() is a method on Optional that will return the value if present, otherwise it will return the value you supplied as the argument to orElse().

Guava Optional

You can shorten it up to this:

firstOptional.or(secondOptional.or(EMPTY_VALUE))

I'm not sure what you meant in your third bullet by "empty". If you meant null then this'll do the trick:

firstOptional.or(secondOptional.orNull())

or() is a method on Optional that will return the value if present, otherwise it will return the value you supplied as the argument to or().

Erik Gillespie
  • 3,929
  • 2
  • 31
  • 48
  • 1
    What type of optionals are you using? http://docs.oracle.com/javase/8/docs/api/index.html?java/util/Optional.html does not have this method – Strikeskids Jul 06 '14 at 20:31
  • \*facepalm\* I mistakenly thought the OP was using Guava's `Optional` instead of Java 8's. I updated my answer to show the syntax for both. – Erik Gillespie Jul 06 '14 at 20:34
  • By ''empty'' I mean `Optional.empty()`. I want to be able to use `ifPresent()` on the resulting optional. – Feuermurmel Jul 07 '14 at 07:44
  • For the Java 8 example, this will unwrap the Optional so that you're just left with a T. – Matt Klein Apr 13 '17 at 15:52
9

I had a few encounters with a problem that might've been solved with JDK 9 Optional::or and couldn't because we use JDK 8. Finally I added a util class with this method:

@SafeVarargs
public static <T> Optional<T> firstPresent(final Supplier<Optional<T>>... optionals) {
    return Stream.of(optionals)
            .map(Supplier::get)
            .filter(Optional::isPresent)
            .findFirst()
            .orElse(Optional.empty());
}

Now you can supply any number of optionals to this method and they'll be lazily evaluated like so:

    final Optional<String> username = OptionalUtil.firstPresent(
            () -> findNameInUserData(user.getBasicData()),
            () -> findNameInUserAddress(user.getAddress()),
            () -> findDefaultUsername());

Now, findNameInUserAddress will only be called if findNameInUserData returns empty. findDefaultUsername will only be called if both findNameInUserData and findNameInUserAddress return empty etc.

seanf
  • 6,504
  • 3
  • 42
  • 52
jahmaican
  • 162
  • 2
  • 8
1

Why not just (Supplier wrapper can be easily added):

    @SafeVarargs
    public static <T> Optional<T> firstPresent(Optional<T>... optionals) {
        return Stream.of(optionals)
                .flatMap(Optional::stream)
                .findFirst();
    }

?

kasopey
  • 355
  • 4
  • 17
-2

I know this question is old, but why don't just use in this kind of cases something proven like Chain-of-responsibility pattern? It is made/designed for cases like yours. And as an additional benefit it's quite easy to add additional services to the list.

Here is a link that describes the Pattern: https://sourcemaking.com/design_patterns/chain_of_responsibility

kaba713
  • 484
  • 6
  • 17
  • How does this apply to my question, which was about combining two `Optional<>` instances? Can you give an example how an implementation would look using this pattern? – Feuermurmel Oct 24 '17 at 16:21