2

最近我写了这样的东西:

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

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

4

6 回答 6

15

这看起来像过早的优化。

这是一个思维陷阱。

在您的申请完成并正确之前,不要担心这样的细节。然后,如果它不够快,就拿出一个分析器,看看程序的时间花在了哪里。

不要浪费脑力去优化可能不引人注目的事情。

于 2012-12-14T17:59:50.653 回答
9

从性能的角度来看,因为b1并且没有在方法中修改,分支预测b2和/或 JIT 编译极有可能优化测试,并且实际条件检查几乎不会(如果有的话)惩罚该方法的性能.

如果不是if(b1)你,if(getB1())那么可能会有更多的改进空间。

于 2012-12-14T18:02:52.507 回答
4

CPU 设计者已经想到了这一点。这称为分支预测。这样做是有效地跳过通常不被调用的分支。这意味着 CPU 将动态删除未使用的分支,几乎不会影响性能。唯一的影响是当预测出错时,因为“回滚”可能很复杂。在你的情况下,布尔值不会改变,所以你不应该看到问题。

于 2012-12-14T20:43:58.580 回答
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:
        }
    }
}
于 2012-12-14T18:09:44.640 回答
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。否则只有一个是正确的,并且逻辑与以前相似。

于 2012-12-14T17:55:10.670 回答
-4

我想你可以将 if 语句移到 while 之外,就像这样

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

但是您实际上并没有获得任何好处,因为您仍然必须评估使 while 循环重复的条件,并且您必须执行两倍于原始代码的频率。

于 2012-12-14T17:59:42.400 回答