62

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

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

或者

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

其他详情:

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

谢谢你的帮助。

4

10 回答 10

70

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

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

所以,

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

是要走的路!

于 2011-03-10T13:02:12.123 回答
23

以下两种方法:

public void oneIf(boolean a, boolean b)
{
    if (a && b)
    {   
    }
}

public void twoIfs(boolean a, boolean b)
{
    if (a)
    {
        if (b)
        {       
        }
    }
}

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

于 2011-03-10T13:11:05.067 回答
6

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

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

于 2011-03-10T13:04:51.420 回答
3

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

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

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

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

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

于 2011-03-10T13:05:12.747 回答
2

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

于 2011-03-10T13:03:43.010 回答
2

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

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

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

于 2016-11-30T13:42:28.740 回答
2

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

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

于 2017-03-27T15:44:26.023 回答
2

我建议将您的表达式提取到具有语义意义的变量中,然后将其传递给您的评估。代替:

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) { ... }
于 2019-12-07T16:58:33.707 回答
1

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

  • 但即使他们不是

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

于 2011-03-10T17:17:10.307 回答
0

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

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

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

于 2021-12-15T02:40:17.683 回答