首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >评估几种条件的有效/优化方法?

问评估几种条件的有效/优化方法?
EN

Stack Overflow用户
提问于 2017-12-06 15:57:00
回答 3查看 45关注 0票数 0

下面哪个代码段(A和B在下面)更高效(性能更好)?为什么?

此外:

  • 编译器是否重新排列validate()方法调用,以便在“需要时”调用它们,即在计算if-语句中的每个单独条件时?换句话说,编译器会把代码片段A当作代码片段B来处理吗?
  • 除了片段A和B之外,还有其他更好的选择吗?

(__validate(...)检查字段(作为参数提供)是否包含有效值)

片段A:

代码语言:javascript
复制
    boolean okTitle = validate(inputTitle);
    boolean okLocation = validate(inputLocation);
    boolean okDuration = validate(inputDuration);
    boolean okReminder = validate(inputReminder);
    boolean okRepetition = validate(inputRepetition);
    boolean okDate = validate(inputDate);

    if(okTitle && (okLocation || okDuration || okReminder || okRepetition || okDate)){
        setEnabled(true);
    }else{
        setEnabled(false);
    }

片段B:

代码语言:javascript
复制
setEnabled(
     validate(inputTitle) && 
     ( validate(inputLocation) || validate(inputDuration) || validate(inputReminder) || validate(inputRepetition) || validate(inputDate) )
   );
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-12-06 16:29:53

编译器会把代码片段A当作代码片段B来处理吗?

不,由于short circuiting,它们不是等效的代码。如果在If语句中有validate(...)调用,那么它将是等价的,并且可以比较字节码,以查看编译器是否有相同的想法。

使用javac Test.java && java Test && javap -c Test测试这两种情况

没有如果

代码语言:javascript
复制
public class Test
{
    public static void main(String[] args)
    {
        int a = 5;
        System.out.println(a > 2 && (a < 6 || a < 4));
    }
}

打印true和字节码:

代码语言:javascript
复制
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_5
       1: istore_1
       2: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       5: iload_1
       6: iconst_2
       7: if_icmple     25
      10: iload_1
      11: bipush        6
      13: if_icmplt     21
      16: iload_1
      17: iconst_4
      18: if_icmpge     25
      21: iconst_1
      22: goto          26
      25: iconst_0
      26: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
      29: return
}

如果

代码语言:javascript
复制
public class Test
{
    public static void main(String[] args)
    {
        int a = 5;
        if(a > 2 && (a < 6 || a < 4))
            System.out.println(true);
        else
            System.out.println(false);
    }
}

按预期打印true,并打印字节码:

代码语言:javascript
复制
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_5
       1: istore_1
       2: iload_1
       3: iconst_2
       4: if_icmple     28
       7: iload_1
       8: bipush        6
      10: if_icmplt     18
      13: iload_1
      14: iconst_4
      15: if_icmpge     28
      18: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      21: iconst_1
      22: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
      25: goto          35
      28: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: iconst_0
      32: invokevirtual #3                  // Method java/io/PrintStream.println:(Z)V
      35: return
}

因此,即使在相同的逻辑流中,它也生成较少的字节码以避免if语句。

(无论如何,这个编译器使用甲骨文的jdk8)

票数 1
EN

Stack Overflow用户

发布于 2017-12-06 16:00:12

在这些情况下,输入通常是有效的,95%的时间和/或验证方法是快速的:如果是这样的话,这两种方法都能正常工作。

如果输入经常无效和/或如果验证方法很慢,并且经常调用该代码,那么您可能希望使用第二种方法,并确保首先测试最有可能的无效原因,以便快速退出条件代码。

票数 2
EN

Stack Overflow用户

发布于 2017-12-06 16:07:16

与编译器无关,代码的执行方式取决于运行时的输入值。

Snippet肯定会比snippet更好的性能,因为A将执行所有calls ()调用,但是B将在满足条件时停止。

当我年轻的时候,我肯定会更喜欢B而不是A,因为我的表现优势。现在,如果validate()方法不是真正的“昂贵”调用,我肯定会选择A,因为它比B更易读和更容易维护。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47678473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档