表现许多​​If语句与长逻辑表达式

时间:2014-05-09 08:03:16

标签: java if-statement logical-operators

如果我有一个很长的逻辑表达式,将它拆分为多个if语句或使用长逻辑表达式是否重要?

示例:

if((A||B)&&(B||C)&&(C||D)&&.....(N||N+1))
      System.out.println("Hello World");

或者这更快

 if(A||B)
  if(B||C)
   if(C||D)
    ...
     if(N||N+1)
      System.out.println("Hello World");

我认为长表达式更快但许多ifs可能更好阅读。 但我不确定,许多if语句是否切实可行?

3 个答案:

答案 0 :(得分:2)

编辑:这是错的,请看下面的编辑

在我的测试用例中,嵌套ifs更快。我不知道为什么。我的预料相反。也许我测试错了。

测试用例

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

public class Test {
    private static final int RUN_TIMES = 100000000;
    private static final int HEATUP_TIMES = 100000;
    private static final int RESET_EVERY = 1000;

    public static void main(String[] args) {
        Test instance = new Test();
        instance.doTest();
    }

    private long a;
    private long b;
    private long c;
    private long d;
    private long e;
    private long f;
    private AtomicLong n;

    private void doTest() {
        Runnable t1 = new Runnable() {
            public void run() {
                if (
                        (a > b || a > c)
                        && (a > d || b > d) 
                        && (c > e || e > f)
                        && (f > a || f > b) 
                        && (f > e || f > a)
                        && (a > f || f > d) 
                        && (d > e || e > d)
                        && (f > e || f > a) 
                        && (f > b || f > a)) {
                    n.incrementAndGet();
                }
            }

            public String toString() {
                return "task1";
            }
        };
        Runnable t2 = new Runnable() {
            public void run() {
                if (a > b || a > c)
                    if (a > d || b > d)
                        if (c > e || e > f)
                            if (f > a || f > b)
                                if ((f > e || f > a))
                                    if ((a > f || f > d))
                                        if ((d > e || e > d))
                                            if ((f > e || f > a))
                                                n.incrementAndGet();
            }
            public String toString() {
                return "task2";
            }
        };

        List<Runnable> tasks = Arrays.asList(t1, t2, t1, t2, t1, t2, t1, t2, t1, t2);
        for (Runnable r: tasks) {
            benchmark(r);
        }
    }

    private void reset() {
        java.util.Random rnd = new java.util.Random();
        this.a = rnd.nextLong();
        this.b = rnd.nextLong();
        this.c = rnd.nextLong();
        this.d = rnd.nextLong();
        this.e = rnd.nextLong();
        this.f = rnd.nextLong();
    }

    private void benchmark(Runnable t) {
        n = new AtomicLong();
        reset();
        for (int i = 0; i < HEATUP_TIMES; i++) {
            t.run();
        }
        long t0 = System.nanoTime();
        int r = 0;
        for (int i = 0; i < RUN_TIMES; i++) {
            if (r == 0) {
                reset();
                r = RESET_EVERY + 1;
            }
            r--;
            t.run();
        }
        long t1 = System.nanoTime();
        System.out.println(String.format("Task %s was run %d times in %.3f ms",
                t, RUN_TIMES, (t1 - t0) / 1000000d));
        System.out.println("n = " + n);
    }
}

<强>结果

Task task1 was run 100000000 times in 753,292 ms
n = 12666654
Task task2 was run 100000000 times in 491,695 ms
n = 12359347
Task task1 was run 100000000 times in 663,144 ms
n = 12530518
Task task2 was run 100000000 times in 499,428 ms
n = 12567555
Task task1 was run 100000000 times in 740,334 ms
n = 12504492
Task task2 was run 100000000 times in 424,854 ms
n = 12379367
Task task1 was run 100000000 times in 721,993 ms
n = 12541529
Task task2 was run 100000000 times in 430,007 ms
n = 12647635
Task task1 was run 100000000 times in 719,680 ms
n = 12598586
Task task2 was run 100000000 times in 432,019 ms
n = 12581569

原子长n是为了测试我没有误解条件并且在条件满足时有事可做。

接受后编辑

正如TheOtherDude指出的那样,第二次测试失踪了。修复结果完全不同。现在两个测试都需要同时进行。

Task task1 was run 100000000 times in 907,538 ms
n = 12401389
Task task2 was run 100000000 times in 941,928 ms
n = 12325413
Task task1 was run 100000000 times in 850,497 ms
n = 12417405
Task task2 was run 100000000 times in 873,328 ms
n = 12571559
Task task1 was run 100000000 times in 840,028 ms
n = 12538526
Task task2 was run 100000000 times in 865,157 ms
n = 12461449
Task task1 was run 100000000 times in 860,125 ms
n = 12252240
Task task2 was run 100000000 times in 862,829 ms
n = 12350338
Task task1 was run 100000000 times in 866,317 ms
n = 12597585
Task task2 was run 100000000 times in 866,483 ms
n = 12538526

答案 1 :(得分:2)

好的,这个问题已经过时了,但我觉得还是值得回答。

任务2缺少一个条件,任务1正在执行。它是最后一个:

&安培;&安培; (f> b || f> a)){

这可能有助于任务2的速度优势。您应该更正并再次测量。

看看OldCurmudgeon给出的第三个选项的速度会很有趣。

另一件事。您会看到执行时间的随机分布。如果执行时间的差异具有统计显着性,那么检查是明智的。

TheOtherDude

答案 2 :(得分:1)

当有可衡量的显着优势时,您应该永远牺牲简单性以获得运行时性能。这里显然没有可衡量的好处,或者你不会问这个问题。

当其他所有方法都失败时 - 尝试简单

您的选择都不简单 - 尝试其他方法。

public boolean goodToGo(boolean... flags) {
    boolean good = true;
    for ( int i = 0; i < flags.length - 1 && good; i++ ) {
        good &= flags[i] || flags[i+1];
    }
    return good;
}

public void test() {
    if ( goodToGo(true, true, false, true, false, false)) {
        System.out.println("Hello");
    }
}