我一直在使用新的Optional type in Java 8,我遇到了一个功能上不支持的常见操作:“或其他可选”
请考虑以下模式:
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条答案
按热度按时间rjzwgtxy1#
这是JDK 9的一部分,形式为方法
or
,它接受Supplier<Optional<T>>
。有关详细信息,请参阅Javadoc、我写的这篇文章或介绍此方法的ticket JDK-8080418。
b4lqfgs42#
给定当前API,最干净的“尝试服务”方法是:
重要的方面不是你必须写一次的(恒定的)操作链,而是添加另一个服务(或修改一般的服务列表)有多容易,在这里,添加或删除一个
()->serviceX(args)
就足够了。由于流的惰性求值,如果前面的服务返回非空的
Optional
,则不会调用任何服务。从Java9开始,您可以将代码简化为
尽管this answer已经包含了一种更简单的JDK9方法。
JDK 16提供了替代方案
尽管这种方法对于接受
Consumer
而不是返回Supplier
的服务方法可能更方便。9w11ddsr3#
不是很漂亮,但这会有用的:
.map(func).orElseGet(sup)
是一个非常方便的模式,它的意思是“如果这个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)
brvekthn4#
也许这就是你想要的Get value from one Optional or another
否则,你可能想看看
Optional.orElseGet
。下面是一个我认为你在寻找的例子:r3i60tvu5#
假设您还在使用JDK8,则有几种选择。
选项1:创建你自己的帮助器方法
例如:
这样你就可以:
选项2:使用图书馆
例如,google guava的Optional支持正确的
or()
操作(就像JDK9一样),例如:(其中每个服务返回
com.google.common.base.Optional
,而不是java.util.Optional
)。kqlmhetl6#
这看起来很适合模式匹配和更传统的带有Some和None实现的Option接口(如Javaslang,FunctionalJava中的那些)或cyclops-react中的lazy Maybe实现。
对于cyclops-react,您还可以在JDK类型上使用结构化的pattern matching。对于Optional,您可以通过visitor pattern匹配存在和不存在的情况。