Java 循环中IF的优雅解决方案

Java 循环中IF的优雅解决方案,java,performance,optimization,Java,Performance,Optimization,最近我写了这样的东西: public void doSomething(boolean b1, boolean b2){ while(true){ if(b1){ doThis(); } if(b2){ doThat(); } } } 但是我真的不喜欢这个解决方案,因为在每次迭代中你都必须检查2个布尔值。所以,作为可能的解决方案,我可以想象在每个循环之前用ifs编写4个while循环,但由于明显的原

最近我写了这样的东西:

public void doSomething(boolean b1, boolean b2){
   while(true){
      if(b1){
         doThis();
      }
      if(b2){
         doThat();
      }
   }
}
但是我真的不喜欢这个解决方案,因为在每次迭代中你都必须检查2个布尔值。所以,作为可能的解决方案,我可以想象在每个循环之前用ifs编写4个while循环,但由于明显的原因,这会降低可维护性。您有什么建议可以使这段代码变得漂亮和有效吗

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
为真,则您希望
执行此操作
执行此操作
。否则,每一个都只有一个是正确的,并且逻辑与以前类似。

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

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

但是你真的没有得到任何东西,因为你仍然需要评估使while循环重复的条件,而且你必须做的频率是原始代码的两倍。

这看起来像是过早的优化

这是一个思维陷阱。

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


不要浪费精力去优化那些可能不值得注意的事情。

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


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

我同意这是过早的优化,但是如果您的语言对短路评估有保证,您可以使用另一种结构。由于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:
        }
    }
}


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

检查这两个布尔人的问题到底是什么?照顾好小山丘,山丘会自行解决。@罗宾:你有没有分析并确定这是一个实际的瓶颈?@罗宾:直觉在这些方面是一个很差的向导。确保代码正确,取出探查器,然后根据探查器告诉您的内容进行优化。可以说,这不是瓶颈,但会给系统带来额外的压力,这在小情况下并不重要,但如果此代码每天执行12万亿次,这并不能真正解决任何问题,因为只有b1的计算结果为false时,
才会触发。Robin的解决方案有可能在适当的条件下同时启动这两个程序。我认为这可能无法满足该代码的业务需求。因为这个问题并不表明这两个布尔值是否相互排斥。可能它们都是为了不同的目的,可以是真的,也可以是假的。更改后的代码更符合原始业务要求。@Perception是的,我现在看到了,因此我修改了我的代码。@Woot4Moo谢谢,但这是编写重复代码。在这个小示例中,这些仅为2行。在现实生活中的例子中,这可能是更多。然后它就不好了。这不再是同一个程序了。呃,我认为这与其说是不成熟的,不如说是正确的编码风格。当“更正确”的解决方案可用时,执行额外步骤没有意义。请记住,我们正在编写证明,而不仅仅是代码。谢谢,但我只是想知道是否有人想过这一点。也许有一个解决方案,哇。真不敢相信有人编辑了我的答案,把“垃圾”改成了“细节”。对不起,如果我冒犯了任何人微妙的感情。我知道美国程序员是贵族类型的。有人编辑,因为这是一个专业的网站,没有必要使用“废话”,而“细节”也是可以接受的。现在,如果这是一个农业站点,“垃圾”可能是一个更好的术语,但我会选择“粪肥”谢谢你,你能解释一下分支预测的含义吗?嗯,你从哪里得到b1和b2总是有相同的值?罗宾分支预测是一个编译器的东西。真的,你应该用谷歌搜索一下,因为我怀疑一条评论能完全涵盖它。无论如何,这是在优化之前您应该分析的另一个原因——编译器可能正在为您解决问题。@Woot4Moo他的意思是在函数的整个执行过程中布尔值不会改变。我认为他并不是说它们之间总是有一个相等的值:)这假设
这个
返回一个布尔值。我认为,这在大多数情况下是不实际的,但对我来说似乎很聪明。真是个好主意。老实说,我看不出
if(b1)doThis()与
if(b1)doThis()之间的性能差异
b1&&doThis()-在这两种情况下,布尔值均为ev