我有两个java.util.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;
}
答案 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
。仅当findDefaultUsername
和findNameInUserData
返回空等时才会调用findNameInUserAddress
。
答案 3 :(得分:-1)
我知道这个问题已经过时了,但为什么不在这种情况下使用一些被证明像责任链模式的东西呢?它是为像您这样的案件制作/设计的。作为额外的好处,可以很容易地向列表中添加其他服务。
以下是描述模式的链接:https://sourcemaking.com/design_patterns/chain_of_responsibility