从一个可选或另一个获得价值

时间:2014-07-06 20:22:22

标签: java java-8 optional

我有两个java.util.Optional个实例,我希望得到一个Optional

  • 具有第一个Optional的值,如果它有值。
  • 如果有值,则具有第二个Optional的值。
  • 为空且两者都不具有值。

有没有直接的方法来做到这一点,即是否已经有一些API可以做到这一点?

以下表达式会这样做,但我必须提到第一个可选的两次:

firstOptional.isPresent() ? firstOptional : secondOptional

这正是com.google.common.base.Optional.or()的作用,但Java 8的API中没有该方法。


aioobe 接受的答案列出了一些替代方法来克服Optional API的遗漏,在这种情况下必须计算这样的值(这回答了我的问题)。我现在选择在我的代码库中添加一个实用程序功能:

public static <T> Optional<T> or(Optional<T> a, Optional<T> b) {
    if (a.isPresent())
        return a;
    else
        return b;
}

4 个答案:

答案 0 :(得分:52)

更新:从Java 9开始(changeset 12885),你可以做到

firstOptional.or(() -> secondOptional);

对于Java 8,请继续阅读...

如果你想避免两次提及firstOptional,你可能不得不采用类似的方式

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

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

但最可读的变体可能只是做

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

如果有人偶然发现了这个问题,但有一个列表的选项,我会建议

Optional<...> opt = optionals.stream()
                             .filter(Optional::isPresent)
                             .findFirst()
                             .orElse(Optional.empty());

答案 1 :(得分:8)

编辑:我完全以为你最初使用的是Guava&#39; Optional。我已经更新了我的答案,为他们各自的Optional类提供了Guava和Java 8语法。

Java 8可选

你可以缩短它:

firstOptional.orElse(secondOptional.orElse(EMPTY_VALUE))

我不确定你在第三个子弹中的意思是什么?#34;空&#34;。如果你的意思是null那么这就是诀窍:

firstOptional.orElse(secondOptional.orElse(null))

orElse()Optional上的一个方法,它会返回值(如果存在),否则它会将您提供的值作为参数返回给orElse()

番石榴可选

你可以缩短它:

firstOptional.or(secondOptional.or(EMPTY_VALUE))

我不确定你在第三个子弹中的意思是什么?#34;空&#34;。如果你的意思是null那么这就是诀窍:

firstOptional.or(secondOptional.orNull())

or()Optional上的一个方法,它会返回值(如果存在),否则它会将您提供的值作为参数返回给or()

答案 2 :(得分:7)

我遇到了一些可能已经用JDK 9 Optional::or解决的问题但是因为我们使用JDK 8而遇到了问题。最后我用这个方法添加了一个util类:

@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());
}

现在你可以为这个方法提供任意数量的选项,它们会像下面那样被懒惰地评估:

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

现在,只有findNameInUserAddress返回空时才会调用findNameInUserData。仅当findDefaultUsernamefindNameInUserData返回空等时才会调用findNameInUserAddress

答案 3 :(得分:-1)

我知道这个问题已经过时了,但为什么不在这种情况下使用一些被证明像责任链模式的东西呢?它是为像您这样的案件制作/设计的。作为额外的好处,可以很容易地向列表中添加其他服务。

以下是描述模式的链接:https://sourcemaking.com/design_patterns/chain_of_responsibility