我有一个表达式(例子)
(value1<15 AND value2>25) OR ((value3>0 and vaue4<5) OR (value5<6 and value7>8))
问题是value1-7是对外部服务的调用,这是昂贵的。我们需要降低成本,因此我们需要进行最少数量的调用来评估此表达式。例如,如果我们有
(value1<15 AND value2>25)
评估为true,我们不需要评估正确的部分,因此我们不需要对外部服务进行无用的调用。当我们需要停止时,如何在java中确定(或者可能只是在数学中),进一步的评估不会产生任何影响?
我有5个工作人员在5个不同的服务器上工作。
第一名工人:
accept(expression)
value1=calculateValue1()
setValueToExpression(expression, 0, value1)
enough=expression.checkIsItEnough()
if(!enough){
determineNextWorker(expression)
sendToNExtWorker()
}
else return expression.evaluate()
第二名工人
accept(expression)
value2=calculateValue2()
setValueToExpression(expression, 1, value2)
enough=expression.checkIsItEnough()
if(!enough){
determineNextWorker(expression)
sendToNextWorker()
}
else return expression.evaluate()
.....................
正如我在评论中所说,我清楚地明白,如果我们可以写
evaluator.evaluate("(value1<5 and value2>6) or (value3>5 and value4>7)")
它像我们所有人都知道的那样评估它,但由于许多原因我没有这种能力。我也无法使函数调用value1()&lt; 15 ... 它同步发生,一个接一个,但即使在不同的服务器上,也有点离线评估。希望很清楚
答案 0 :(得分:3)
标准条件将以这种方式工作(短路),因为它只会在必要时评估表达式(如果||
条件的第一部分为真,则不会评估其余部分):
if ((value1() < 15 && value2() > 25) || (value3() > 0 && vaue4() < 5) ...)
请注意,我已经通过方法调用替换了值 - 如果您预先计算每个值,那么它将不起作用...
示例:
value1() < 15
返回false,则不会调用value2()
value1() < 15 && value2() > 25
为真,则不会评估value3()
和value4()
。<强>参考文献:强>
见JLS #15.23(强调我的):
条件和运算符
&&
类似于&
, 但仅在其左侧操作数的值为真时才计算其右侧操作数 强>
同样在JLS #15.24中:
条件或运算符
||
运算符类似于|
, 但仅在其左侧操作数的值为false时评估其右侧操作数 强>
答案 1 :(得分:3)
考虑正常的短路中间代码:
(value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8))
if value1<15 goto value2_test else goto value3_test
value2_test:
if value2>25 goto success else goto value3_test
value3_test:
if value3>0 goto value4_test else goto value5_test
value4_test:
if value4<5 goto success else goto value5_test
value5_test:
if value5<6 goto value7_test else goto fail
value7_test:
if value7>8 goto success else goto fail
您可以通过表达表达式的树表示,并绕过由树而不是整个表达式表示的子表达式来大大简化事物。
例如,第一个工作人员将有两个子表达式:value2>25
和(value3>0 and value4<5) OR (value5<6 and value7>8)
。如果测试成功,则选择第一个,如果测试失败,则选择第二个。
value2&gt; 25工作人员将有两个子表达式:“成功”和(value3>0 and value4<5) OR (value5<6 and value7>8)
我不知道有任何库可以进行转换。如果它存在,它将在编译器构造的领域。
我会非常努力地将其改为一个工人可以组织工作的事情,并且只需要其他工人来评估一个关系条件。
=============================================== ========================= 更多细节,因为这似乎是OP正在寻找的那种答案:
术语:
value2>25
仅考虑产品总和表达式,例如(value1<15 AND value2>25) OR ((value3>0 and value4<5) OR (value5<6 and value7>8))
。这不是一个非常重要的限制。数字逻辑设计中使用的许多优化和简化取决于将任意逻辑表达式转换为乘积和。
在每个步骤中,调用表达式的主要术语的worker。根据表达式和测试结果,它可以声明成功,声明失败或计算必须传递给工作者的新表达式。
if this worker's condition is true
if more terms in current product
remove the leading term from the current product
pass the new expression to the worker for the next term
else
declare success
else
if there is another product
remove the leading product from the expression
pass the new expression to the worker for the new leading product's leading term
else
declare failure
答案 2 :(得分:0)
默认情况下,条件逻辑评估获取评估结果所需的最少条件。这不是Java特有的。这就是事情的运作方式。此外,在您的情况下,分组括号是完全可选的。
根据您的使用情况,您可能希望在条件内向前推进最可能为真的表达式。如果适用,也许可以考虑将某些结果缓存一段时间。