我有一堆谓词,我想用逻辑“与”将它们链接在一起,以便仅当所有单个谓词的计算结果都为 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 如何实现默认谓词方法,所以如果我错了,请纠正我。
有什么办法可以两全其美吗?如果不是,我是否应该选择更具可读性的方法,而不是可能会带来非常边际的性能提升,反之亦然?
最佳答案
一般来说,任何感知到的边际性能考虑都优先考虑可读性。对于大多数谓词,我们希望它们能够非常快地执行,并且很难注意到这样的组合谓词提前短路并且经常短路,而与那些较晚短路或根本不短路的谓词相比。
因此,从第一个选项开始,即更具可读性的选项,它不会嵌套谓词来扰乱操作顺序。
如果您确实发现由于某种探查器统计数据或基准性能运行而存在性能问题,那么您可以重新排序操作以获得性能优势。
- 您可以选择首先放置最有可能短路的谓词,以避免执行不会影响结果的谓词带来不必要的开销。因为您在它们之间使用
and
,所以这些更有可能返回false
。 - 如果您多次调用这些链接谓词,请查看是否可以找到任何不变的谓词,例如不依赖于循环迭代索引,并保存这些结果,这样它们就不需要一遍又一遍地重复。
- 如果您发现其中一个谓词计算量大,并且在循环中不是不变的,因此需要一遍又一遍地执行它,则将其放在链的最后,以查看先前的谓词是否可能会短路 -电路,因此根本不需要执行。
但这也不应该影响可读性。您不需要像以前那样嵌套谓词;最多你需要重新排序它们,例如
Predicate composedPredicate =
predicate4
.and(predicate2)
.and(predicate1)
.and(predicate3)
如果您注意到 predicate4
很少返回 true
并且 predicate3
计算量很大。
关于java - Java 中链接谓词的首选方式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57877608/