哪个更好:多个“if”语句或一个带有多个条件的“if”?

Posted

技术标签:

【中文标题】哪个更好:多个“if”语句或一个带有多个条件的“if”?【英文标题】:What is better: multiple "if" statements or one "if" with multiple conditions? 【发布时间】:2011-07-12 17:01:32 【问题描述】:

对于我的工作,我必须开发一个小型 Java 应用程序来解析非常大的 XML 文件(约 30 万行)以选择非常具体的数据(使用 Pattern),所以我正在尝试对其进行一些优化。我想知道这 2 个 sn-ps 之间哪个更好:

if (boolean_condition && matcher.find(string)) 
    ...

if (boolean_condition) 
    if (matcher.find(string)) 
        ...
    

其他细节:

这些 if 语句在循环内的每次迭代中执行(约 20k 次迭代) boolean_condition 是使用外部函数在每次迭代中计算得到的 boolean 如果boolean 设置为false,我不需要测试正则表达式是否匹配

感谢您的帮助。

【问题讨论】:

没有简单的答案。查看this SO discussion关于同一主题的信息。 没有任何性能差异。这纯粹是一个风格问题,这使它成为一个见仁见智的问题。 【参考方案1】:

我遵循的一条黄金法则是尽可能“避免嵌套”。但如果它的代价是使我的单个 if 条件过于复杂,我不介意将它嵌套出来。

除了您使用的是短路&& 运算符。所以如果布尔值是假的,它甚至不会尝试匹配!

所以,

if (boolean_condition && matcher.find(string)) 
    ...

是要走的路!

【讨论】:

谢谢!我不确定运算符是否设置为 false,匹配是否会执行。 考虑if(x != null && x.isY());如果 && 没有 使评估短路,那会在 x == null 的瞬间炸毁你的脸。 确实如此!但我必须确定,所以我问 +adarshr 好吧,即使在嵌套的 if 中,它也会短路,因为如果外部 if 评估为 false,那么它不会费心检查内部 if,如果第一个评估为false 会短路 @user 你不会在评估之前检查 null 吗?常识说是? ArgumentNullException 也许?【参考方案2】:

第一个。如果像这样嵌套,我会尽量避免,我认为这是糟糕的样式/丑陋的代码,&& 会短路,并且只有在布尔值为真时才使用 matcher.find() 进行测试。

【讨论】:

【参考方案3】:

两种方式都可以,如果第一个条件为假,则不会测试第二个条件。

使用使代码更具可读性和可理解性的代码。仅针对两个条件,第一种方式更具逻辑性和可读性。与&&||! 相关联的 5 或 6 个条件可能不再是这种情况。

【讨论】:

【参考方案4】:

Java 对这些布尔运算符使用短路,因此这两种变体在功能上是相同的。因此,如果boolean_condition 为假,则不会继续匹配

归根结底,你会发现它更易于阅读和调试,但如果你最终得到大量大括号,深度嵌套可能会变得笨拙

如果条件变长,提高可读性的一种方法是简单地将其拆分为多行:

if(boolean_condition &&
   matcher.find(string))

    ...

此时唯一的选择是是否放 && 和 ||在上一行的末尾,或当前行的开头。

【讨论】:

【参考方案5】:

以下两种方法:

public void oneIf(boolean a, boolean b)

    if (a && b)
       
    


public void twoIfs(boolean a, boolean b)

    if (a)
    
        if (b)
               
        
    

为方法主体生成完全相同的字节码,因此不会有任何性能差异,这意味着它纯粹是您使用的风格问题(我个人更喜欢第一种风格)。

【讨论】:

我不会怀疑public void noIfs(boolean a, boolean b) 方法是否也产生了相同的字节码 ;-) @Axel 不,它没有(我刚刚检查过!)这并不奇怪,Java 编译器几乎没有优化,让 JVM 在运行时完成。 我认为解析器在第二个构造中还有更多工作要做,因为它必须确定下一条语句是'if'还是其他东西。另一方面,在第一个构造中,它只会解析条件,并且知道跟随是条件的一部分。【参考方案6】:

在性能方面,它们是相同的。

但即使他们不是

几乎可以肯定,这段代码中占主导地位的是matcher.find(string),因为它是一个函数调用。

【讨论】:

【参考方案7】:

我倾向于看到太多的 && 和 ||串在一起形成逻辑汤,通常是微妙错误的来源。

添加另一个 && 或 || 太容易了到你认为正确的地方,打破现有的逻辑。

因此,作为一般规则,我尽量不使用其中任何一个,以避免随着需求的变化而增加更多内容的诱惑。

【讨论】:

【参考方案8】:

如果您希望遵守Sonar rule squid:S1066,您应该折叠 if 语句以避免警告,因为它声明:

应合并可折叠的“if”语句

【讨论】:

【参考方案9】:

我建议将您的表达式提取为具有语义意义的变量,然后将其传递给您的评估。而不是:

if (boolean_condition && matcher.find(string))  ... 

将表达式分配给变量,然后计算变量:

const hasItem = boolean_condition && matcher.find(string)

if (hasItem)  ... 

使用这种方法,即使是最复杂的评估也可以保持可读性:

const hasItem = boolean_condition && matcher.find(string)

const hasOtherThing = boolean_condition || boolean_condition

const isBeforeToday = new Date(string) < new Date()

if (hasItem && hasOtherThing && isBeforeToday)  ... 

【讨论】:

【参考方案10】:

由于“&&”,大多数人更喜欢使用下面的那个。

if (boolean_condition && matcher.find(string)) 
...

我们通常将这些称为“短路(或最低评估)”。这意味着只有当第一个参数没有足够的信息来确定表达式的值时,才会评估第二个参数(这里是“matcher.find(string)”)。例如,如果“boolean_condition”是false,那么整体条件一定是false(因为这里是逻辑AND 运算符)。然后编译器不会检查第二个参数,这将导致减少代码的运行时间。

【讨论】:

这不是已经包含在现有答案中了吗? (更重要的是——这可能在 2011 年被认为是热门话题,但在 2021 年,这个问题显然过于基于观点而不能成为话题,这意味着How to Answer 适用)。

以上是关于哪个更好:多个“if”语句或一个带有多个条件的“if”?的主要内容,如果未能解决你的问题,请参考以下文章

Go语言第五篇:Go条件语句

在 if 语句中格式化多个“或”条件的最佳方法

如何在带有 Liquid 的 if 语句中使用多个参数

我正在尝试将我的多个数组方法调用简化为 if 语句或更简单的基于条件的语句

思考性能问题

R语言 决策