最近我写了这样的话:
public void doSomething(boolean b1, boolean b2){
while(true){
if(b1){
doThis();
}
if(b2){
doThat();
}
}
}
但我真的不喜欢这个解决方案,因为在每次迭代中你都要检查2个布尔值。因此,作为可能的解决方案,我可以想象在每个循环之前使用ifs编写4个while循环,但是由于显而易见的原因,这在可维护性方面很糟糕。您有什么建议可以使这段代码变得更好,更有效吗?
答案 0 :(得分:15)
这看起来像是过早优化。
这是一个心灵陷阱。
在您的申请完成并正确之前,请不要担心此类详细信息。然后,如果它不够快,请取出一个分析器,看看程序的时间花在哪里。
不要浪费精神上的努力来优化可能不值得注意的事情。
答案 1 :(得分:9)
从性能角度来看,由于b1
和b2
未在方法中进行修改,因此branch prediction和/或JIT编译极有可能优化测试,并且实际情况检查很难(如果有的话)惩罚该方法的表现。
如果您if(b1)
代替if(getB1())
,那么可能会有更多改进空间。
答案 2 :(得分:4)
CPU设计者已经考虑过这一点。它被称为分支预测。这样做有效地跳过了通常不被调用的分支。这意味着CPU将动态删除未使用的分支,而不会影响性能。这种情况的唯一影响是预测错误,因为“回滚”可能很复杂。在你的情况下,布尔值不会改变,所以你不应该看到问题。
答案 3 :(得分:1)
我同意这是过早的优化,但如果您的语言有短路评估保证,那么这是您可以使用的另一种结构。由于java不允许您将void
返回类型转换为boolean
,因此您需要修改doThis()
和doThat()
以返回boolean
。
public void doSomething(boolean b1, boolean b2){
while(true){
b1 && doThis(),
b2 && doThat();
}
}
如果(x && foo())
的值为真,x
将仅执行该函数,否则将启动短路评估。
您必须非常小心,您的编译器不会优化掉整个表达式,因为实际上没有赋值。
在所有情况下避免两种比较的真实可能优化是在内循环中使用switch语句。
public void doSomething(boolean b1, boolean b2){
int state = (b1 ? 1 : 0) + (b2 ? 2 : 0);
while(true){
switch (state){
case 1: doThis(); break;
case 3: doThis();
case 2: doThat();
default:
}
}
}
答案 4 :(得分:0)
public void doSomething(boolean b1, boolean b2){
while(true){
if(b1 && b2)
{
doThis();
doThat();
}
else if(b1){
doThis();
}
else if(b2){
doThat();
}
}
}
编译器将对此进行优化,而不是在循环中触发每个if / else if块。类似于switch语句。如果b1
和b2
为真,那么您需要doThis
和doThat
。另外,每个中只有一个是真的,逻辑类似于以前的逻辑。
答案 5 :(得分:-4)
我想你可以在if之外移动if语句,就像这样
if (b1) {
while (true) {
doThis();
}
}
if (b2) {
while (true) {
doThat();
}
}
但是你真的没有获得任何东西,因为你仍然必须评估使while循环重复的条件,并且你必须比原始代码多两倍。