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

Feu*_*mel 48 java optional java-8

我有两个java.util.Optional实例,我想得到一个Optional:

  • 如果它有值,则具有第一个Optional的值.
  • 如果它有值,则具有第二个Optional的值.
  • 是空的既不是Optional也有值.

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

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

firstOptional.isPresent() ? firstOptional : secondOptional
Run Code Online (Sandbox Code Playgroud)

这正是com.google.common.base.Optional.or()如此,但Java 8的API中不存在该方法.


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

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

aio*_*obe 65

更新:从Java 9(变更集12885)开始,您可以这样做

firstOptional.or(() -> secondOptional);
Run Code Online (Sandbox Code Playgroud)

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

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

firstOptional.map(Optional::of).orElse(secondOptional);
Run Code Online (Sandbox Code Playgroud)

要么

Optional.ofNullable(firstOptional.orElse(secondOptional.orElse(null)));
Run Code Online (Sandbox Code Playgroud)

但最可读的变体可能就是这样做

Optional<...> opt = firstOptional.isPresent()  ? firstOptional
                  : secondOptional.isPresent() ? secondOptional
                  : Optional.empty();
Run Code Online (Sandbox Code Playgroud)

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

Optional<...> opt = optionals.stream()
                             .filter(Optional::isPresent)
                             .findFirst()
                             .orElse(Optional.empty());
Run Code Online (Sandbox Code Playgroud)

  • 我认为值得一提的是,Java 8 中相当于 Java 9 `Optional.or` 的是 `firstOptional.map(Optional::of).orElseGet(()-&gt;secondOptional)`。如果“firstOptional”为空,它仅评估“secondOptional”。其行为类似于逻辑“||”。 (2认同)

Eri*_*pie 8

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

Java 8可选

你可以缩短它:

firstOptional.orElse(secondOptional.orElse(EMPTY_VALUE))
Run Code Online (Sandbox Code Playgroud)

我不确定你的第三个子弹是什么意思"空".如果你的意思是null那么这就行了:

firstOptional.orElse(secondOptional.orElse(null))
Run Code Online (Sandbox Code Playgroud)

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

番石榴可选

你可以缩短它:

firstOptional.or(secondOptional.or(EMPTY_VALUE))
Run Code Online (Sandbox Code Playgroud)

我不确定你的第三个子弹是什么意思"空".如果你的意思是null那么这就行了:

firstOptional.or(secondOptional.orNull())
Run Code Online (Sandbox Code Playgroud)

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


小智 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());
}
Run Code Online (Sandbox Code Playgroud)

现在你可以为这个方法提供任意数量的选项,它们将被懒惰地评估,如下所示:

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

现在,findNameInUserAddress只有在findNameInUserData返回为空时才会被调用.findDefaultUsername将仅都叫findNameInUserDatafindNameInUserAddress返回空等.