有没有一种优雅的方法来获取Java中多个方法返回的第一个非空值?
你自己已经看过很多次了,我敢肯定:
public SomeObject findSomeObject(Arguments args) {
SomeObject so = queryFirstSource(args); // the most likely source first, hopefully
if (so != null) return so;
so = querySecondSource(args); // a source less likely than the first, hopefully
if (so != null) return so;
so = queryThirdSource(args); // a source less likely than the previous, hopefully
if (so != null) return so;
// and so on
}
我们有不同的来源,我们可以搜索对象。作为一个更生动的例子,我们可以想象我们首先检查一个用户ID是否在特权用户列表中。如果没有,我们会检查用户标识是否在允许的用户列表中。否则,我们返回 null。(这不是最好的例子,但我希望这是一个足够生动的例子。
番石榴为我们提供了一些可以美化上述代码的帮助器:
public SomeObject findSomeObject(Arguments args) {
// if there are only two objects
return com.google.common.base.Objects.firstNonNull(queryFirstSource(args), querySecondSource(args));
// or else
return com.google.common.collect.Iterables.find(
Arrays.asList(
queryFirstSource(args)
, querySecondSource(args)
, queryThirdSource(args)
// , ...
)
, com.google.common.base.Predicates.notNull()
);
}
但是,正如我们当中更有经验的人已经看到的那样,如果查找(即)需要一定的时间,这可能会很糟糕。这是因为我们现在首先查询所有源,然后将结果传递给方法,该方法在那些结果中找到第一个不是 。queryXXXXSource(args)
null
与第一个示例相反,在第一个示例中,仅当前者不返回某些内容时才评估下一个源,而第二个解决方案最初可能看起来更好,但性能可能差得多。
这就是我们提出我的实际问题的地方,也是我建议的一些东西,我希望有人已经实现了它的基础,或者有人可能会提出一个甚至聪明的解决方案。
用简单的英语:有人已经实现了这样一个defferedFirstNonNull
(见下文)或类似的东西吗?有没有一个简单的普通Java解决方案可以通过新的Stream框架来实现这一点?您能提出另一个实现相同结果的优雅解决方案吗?
规则:Java 8是允许的,以及活跃的维护和知名的第三方库,如Google的Guava或Apache的Commons Lang,Apache许可证或类似的(没有GPL!
建议的解决方案:
public SomeObject findSomeObject(Arguments args) {
return Helper.deferredFirstNonNull(
Arrays.asList(
args -> queryFirstSource(args)
, args -> querySourceSource(args)
, args -> queryThirdSource(args)
)
, x -> x != null
)
}
因此,该方法将一个接一个地计算每个lambda表达式,并且一旦谓词()为真(即我们找到了匹配项),该方法将立即返回结果,并且不会查询任何进一步的源。defferedFirstNonNull
x -> x != null
PS:我知道表达式可以缩短为.但这会使提出的解决方案更难阅读,因为乍一看并不明显会发生什么。args -> queryXXXXSource(args)
queryXXXXSource