环路中IF的优雅解决方案

时间:2012-12-14 17:53:16

标签: java performance optimization

最近我写了这样的话:

public void doSomething(boolean b1, boolean b2){
   while(true){
      if(b1){
         doThis();
      }
      if(b2){
         doThat();
      }
   }
}

但我真的不喜欢这个解决方案,因为在每次迭代中你都要检查2个布尔值。因此,作为可能的解决方案,我可以想象在每个循环之前使用ifs编写4个while循环,但是由于显而易见的原因,这在可维护性方面很糟糕。您有什么建议可以使这段代码变得更好,更有效吗?

6 个答案:

答案 0 :(得分:15)

这看起来像是过早优化。

这是一个心灵陷阱。

在您的申请完成并正确之前,请不要担心此类详细信息。然后,如果它不够快,请取出一个分析器,看看程序的时间花在哪里。

不要浪费精神上的努力来优化可能不值得注意的事情。

答案 1 :(得分:9)

从性能角度来看,由于b1b2未在方法中进行修改,因此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语句。如果b1b2为真,那么您需要doThisdoThat。另外,每个中只有一个是真的,逻辑类似于以前的逻辑。

答案 5 :(得分:-4)

我想你可以在if之外移动if语句,就像这样

if (b1) {
    while (true) {
        doThis();
    }
}
if (b2) {
    while (true) {
        doThat();
    }
}

但是你真的没有获得任何东西,因为你仍然必须评估使while循环重复的条件,并且你必须比原始代码多两倍。