我有一堆谓词,我想将它们与逻辑“和”链接在一起,以便只有在所有单个谓词的评估结果都为true时,最终结果才为true。
如我所见,有两种写方法。我可以像这样将它们链接在一起:
Predicate composedPredicate =
predicate1
.and(predicate2)
.and(predicate3)
.and(predicate4)
或者我可以使用这样的更嵌套的方法:
Predicate composedPredicate =
predicate1
.and(predicate2
.and(predicate3
.and(predicate4)))
显然,选项1更具可读性,但似乎效率可能略低。我认为选项1大致等于:
(((p1 && p2) && p3) && p4)
选项2为:
(p1 && (p2 && (p3 && p4)))
在第二种情况下,将对第一个参数p1
求值,如果它为假,则整个事件立即短路,您就完成了。在第一个选项中,第一个参数实际上是整个表达式((p1 && p2) && p3)
,它本身具有(p1 && p2)
的第一个参数,而后者又将p1
作为其第一个参数。基本上,在实际可以评估p1之前,您需要再进行2个“步骤”。我实际上不知道Java如何实现默认谓词方法,因此如果我在这里错了,请纠正我。
有什么办法可以做到两全其美吗?如果不是,相对于性能提升幅度很小或反之亦然,我是否应该采用更具可读性的方法呢?
答案 0 :(得分:4)
通常,在任何可感知的边际性能方面,都应考虑可读性。对于大多数谓词,我们希望它们执行得非常快,并且很难注意到这样的组合谓词:早期短路且经常短路,而不是晚期短路或根本不短路。
因此,从您的第一个选项(即更具可读性的选项)开始,即不要嵌套谓词以弄乱操作顺序。
如果由于某种探查器统计信息或基准性能运行而确实发现了性能问题,则可以重新排序操作以获得性能优势。
and
,所以它们更可能返回false
。但这也不应该影响可读性。您不必像已经完成的那样嵌套谓词。最多您需要重新排序它们,例如
Predicate composedPredicate =
predicate4
.and(predicate2)
.and(predicate1)
.and(predicate3)
如果您注意到predicate4
很少返回true
并且predicate3
的计算量很大。