Get value from one Optional or another

前端 未结 4 1033
轮回少年
轮回少年 2020-11-28 06:55

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 v
相关标签:
4条回答
  • 2020-11-28 07:27

    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

    0 讨论(0)
  • 2020-11-28 07:33

    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.

    0 讨论(0)
  • 2020-11-28 07:35

    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());
    
    0 讨论(0)
  • 2020-11-28 07:37

    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().

    0 讨论(0)
提交回复
热议问题