哪种处理奇数和偶数元素最有效?

时间:2016-12-15 07:48:42

标签: java arrays

方法1

int[] arr = new int[10];
for(int i = 0; i < arr.length; i++) {
    if(i % 2 == 0)
       // do stuff
    else
       // do stuff
}

方法2

int[] arr = new int[10];
boolean flag = true;
for(int i = 0; i < arr.length; i++) {
    if(flag) {
       // do stuff
       flag = false;
    }
    else {
       // do stuff
       flag = true;
    }
}

方法3

int[] arr = new int[10];
for(int i = 0; i < arr.length; i++) {
    if((i & 1) == 1)
       // do stuff
    else
       // do stuff
}

方法4

int[] arr = new int[10];
for(int i = 0; i < arr.length; i+=2) {
   // do stuff for even numbers
}
for(int i = 1; i < arr.length; i+=2) {
   // do stuff for odd numbers
}

从方法1切换到方法3时,a guy got 66% performance boost.

在拥有大团队的生产环境中,选择2到3之间的方法有什么优点和缺点?

修改

哪种方法最好,在分发团队时不会牺牲太多的可读性?

1 个答案:

答案 0 :(得分:3)

如果表现符合你的要求,我会打赌我的钱:

    for(int i = 0; i < arr.length; i+=2) {
        // do even stuff
    }
    for(int i = 1; i < arr.length; i+=2) {
        // do odd stuff
    }

这样你就可以跳过整个if-else部分。并且更多和“和”版本一样快。让我演示给你看;这里我们有4种不同的同一方法实现:

private static long withModulus(int[] arr) {
    long elapsedTime = System.nanoTime();
    for(int i = 0; i < arr.length; i++) {
        List list;
        if ((i % 2) == 0) {
            list = new ArrayList<>();
            list.add(new Object());
        } else {
            list = new LinkedList<>();
            list.add(new Object());
        }
    }
    return (System.nanoTime() - elapsedTime);
}

private static long withFlag(int[] arr) {
    long elapsedTime = System.nanoTime();
    for(int i = 0; i < arr.length; i++) {
        List list;
        boolean flag = true;
        if (flag) {
            list = new ArrayList<>();
            list.add(new Object());
            flag = false;
        } else {
            list = new LinkedList<>();
            list.add(new Object());
            flag = true;
        }
    }
    return (System.nanoTime() - elapsedTime);
}

private static long withAnd(int[] arr) {
    long elapsedTime = System.nanoTime();
    for(int i = 0; i < arr.length; i++) {
        List list;
        if ((i & 1) == 1) {
            list = new ArrayList<>();
            list.add(new Object());
        } else {
            list = new LinkedList<>();
            list.add(new Object());
        }
    }
    return (System.nanoTime() - elapsedTime);
}

private static long withTwoLoops(int[] arr) {
    long elapsedTime = System.nanoTime();
    for(int i = 0; i < arr.length; i+=2) {
        List list;
        list = new ArrayList<>();
        list.add(new Object());
    }
    for(int i = 1; i < arr.length; i+=2) {
        List list;
        list = new LinkedList<>();
        list.add(new Object());
    }
    return (System.nanoTime() - elapsedTime);
}

现在是时间部分:

public static void main(String[] args) {
    int[] arr = new int[10000000];
    // Warm up
    withModulus(arr);
    withFlag(arr);
    withAnd(arr);
    withTwoLoops(arr);
    // Timing
    int iterations = 100;
    long meanModulus = 0, meanFlag = 0, meanAnd = 0, meanTwoLoops = 0;
    for (int i = 0; i < iterations; i++) {
        meanModulus += withModulus(arr);
    }
    for (int i = 0; i < iterations; i++) {
        meanFlag += withFlag(arr);
    }
    for (int i = 0; i < iterations; i++) {
        meanAnd += withAnd(arr);
    }
    for (int i = 0; i < iterations; i++) {
        meanTwoLoops += withTwoLoops(arr);
    }
    System.out.println("Modulus: "+(meanModulus/iterations)+" ms");
    System.out.println("Flag: "+(meanFlag/iterations)+" ms");
    System.out.println("And: "+(meanAnd/iterations)+" ms");
    System.out.println("Two loops: "+(meanTwoLoops/iterations)+" ms");
}

结果:

Modulus: 82331604 ms
Flag: 96305740 ms
And: 80845864 ms
Two loops: 79633999 ms

您可以尝试使用不同的数组大小,但对于大于10000的任何内容,双循环选项是最快的。
经过许多不同的运行和测试后,有时“和”版本最快,有时候“两个循环”是。甚至“模数”版本在其中一个测试中也是最快的。在制作中,它主要取决于你在循环中所做的事情,而不是条件本身。