Java 从一个 Optional 或另一个获取价值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24599996/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 13:22:06  来源:igfitidea点击:

Get value from one Optional or another

javajava-8optional

提问by Feuermurmel

I have two java.util.Optionalinstances and I want to get an Optionalthat either:

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

  • 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.
  • 具有第一个 Optional 的值,如果它有值的话。
  • 具有第二个 Optional 的值,如果它有值的话。
  • 空的 Optional 都没有值。

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

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

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.

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



The accepted answer by aioobelists a few alternative approaches to overcome this omission of the OptionalAPI 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:

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

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

采纳答案by aioobe

Java 9 and above:

Java 9 及更高版本:

firstOptional.or(() -> secondOptional);

Java 8 and below

Java 8 及以下

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

如果你想避免提及firstOptional两次,你可能不得不使用类似的东西

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 listof optionals, I'd suggest something like

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

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

回答by Erik Gillespie

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

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

Java 8 Optional

Java 8 可选

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:

我不确定你在第三个项目中的“空”是什么意思。如果您的意思是 null 那么这将起作用:

firstOptional.orElse(secondOptional.orElse(null))

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

orElse()是一个方法Optional,如果存在,它将返回值,否则它将返回您作为参数提供给 的值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:

我不确定你在第三个项目中的“空”是什么意思。如果您的意思是 null 那么这将起作用:

firstOptional.or(secondOptional.orNull())

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

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

回答by kaba713

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

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

回答by jahmaican

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

我遇到了一些问题,这个问题可能已经用 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());
}

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, findNameInUserAddresswill only be called if findNameInUserDatareturns empty. findDefaultUsernamewill only be called if both findNameInUserDataand findNameInUserAddressreturn empty etc.

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