我一直在使用新的Optional type in Java 8,并在功能上支持我've come across what seems like a common operation that isn':"orElseOptional"
考虑以下模式:
Optional<Result> resultFromServiceA = serviceA(args);
if (resultFromServiceA.isPresent) return result;
else {
Optional<Result> resultFromServiceB = serviceB(args);
if (resultFromServiceB.isPresent) return resultFromServiceB;
else return serviceC(args);
}
这种模式有很多种形式,但归结为在一个可选项上需要一个“orElse”,它接受一个生成一个新的可选项的函数,仅当当前的一个不存在时才被调用 .
它的实现看起来像这样:
public Optional<T> orElse(Supplier<Optional<? extends T>> otherSupplier) {
return value != null ? this : other.get();
}
我很好奇是否有这样的方法不存在的原因,如果我只是以一种无意的方式使用Optional,以及人们提出了处理这种情况的其他方式 .
我应该说,我认为涉及自定义实用程序类/方法的解决方案并不优雅,因为使用我的代码的人不一定知道它们存在 .
另外,如果有人知道,这样的方法是否会包含在JDK 9中,我可以在哪里提出这样的方法?对我来说,这似乎是对API的一个相当明显的遗漏 .
6 回答
这是JDK 9的一部分,形式为
or
,需要Supplier<Optional<T>>
. 那么你的例子就是:有关详细信息,请参阅the Javadoc或this post我写道 .
鉴于当前的API,最干净的“尝试服务”方法将是:
重要的方面不是您必须编写一次的(常量)操作链,而是添加其他服务(或修改服务列表)是多么容易 . 在这里,添加或删除单个_588348就足够了 .
由于对流的延迟评估,如果前面的服务返回非空
Optional
,则不会调用任何服务 .它不漂亮,但这将工作:
.map(func).orElseGet(sup)
是一个非常方便的模式,可用于Optional
. 这意味着“如果Optional
包含值v
,请给我func(v)
,否则给我sup.get()
” .在这种情况下,我们调用
serviceA(args)
并获得Optional<Result>
. 如果Optional
包含值v
,我们想得到Optional.of(v)
,但如果它是空的,我们想得到serviceB(args)
. 用更多替代品冲洗重复 .这种模式的其他用途是
.map(Stream::of).orElseGet(Stream::empty)
.map(Collections::singleton).orElseGet(Collections::emptySet)
也许这就是你所追求的:Get value from one Optional or another
否则,您可能需要查看Optional.orElseGet . 以下是我认为你所追求的一个例子:
假设你还在JDK8上,有几种选择 .
选项#1:制作自己的帮助方法
例如 . :
这样你就可以做到:
选项#2:使用库
例如 . google guava的Optional支持正确的
or()
操作(就像JDK9一样),例如:(其中每个服务返回
com.google.common.base.Optional
,而不是java.util.Optional
) .这看起来非常适合模式匹配和更传统的Option接口与Some和None实现(例如Javaslang,FunctionalJava中的那些)或cyclops-react中的懒惰Maybe实现 . 我是这个库的作者 .
使用cyclops-react,您还可以在JDK类型上使用结构pattern matching . 对于Optional,您可以通过visitor pattern匹配当前和不存在的情况 . 看起来像这样 -