8

当您需要索引时,循环遍历数组的最佳方法是什么?

选项1:

int len = array.length;
for (int i = 0; i < len; ++i) {
    array[i] = foo(i);
}

选项 2:

for (int i = 0; i < array.length; i++) {
    array[i] = foo(i);
}

或者,没关系?或者有更好的方法吗?只是指出差异:在一种情况下,数组的长度被评估为循环中测试的一部分,尽管编译器通常应该优化它。


其次,这里有++i什么不同i++吗?如果它是 C++,我肯定更喜欢++i,但不确定 Java。

4

4 回答 4

6

i++vs++i在这种特殊情况下无关紧要。虽然 C 大师会告诉您将 array.length 存储在变量中,但现代优化编译器在这种情况下不需要这样做,只要长度在循环中没有改变。如果您真的很担心,您可以对两者进行基准测试,但.length实际上并不需要每次遍历整个数组就可以了。

于 2012-09-29T02:43:44.907 回答
6

通常这两种方法是等价的。你应该注意,在

for (int i = 0 ; i < foo() ; i++) {
    ...
}

foo()每次迭代之前调用一次(而不是在第一次迭代之前只调用一次),因此您可能希望通过执行类似的操作来考虑更复杂的情况

int n = foo();
for (int i = 0 ; i < n ; i++) {
    ...
}

这类似于您的Option 1。所以我会说选项 1肯定是两者中更安全的一个,但大多数时候它不应该对你使用的产生重大影响。


至于你的第二个问题:++i首先增加你的变量然后检索它的值,i++首先检索值然后增加。只需尝试以下两段代码:

int i = 0;
System.out.println(++i);
------------------------
int i = 0;
System.out.println(i++);

第一个打印1,但第二个打印0。当然,何时++ii++独自一人并没有什么区别。

于 2012-09-29T02:45:28.067 回答
0

for for循环中是否使用“array.length”:一般编译器会做一些优化,结果相当于在for循环中使用了变量

对于 "i++" 和 "++i" 在 C++ 中,++i 是首选且更高效,但在 Java 中,它们在这种情况下是等价的。

于 2012-09-29T03:12:29.787 回答
0

除了 arshaji 响应之外,我还想知道size()在循环中使用与提前存储相比是否有性能优势。我相信结果表明编译器确实优化了一些东西并且访问列表的长度与访问变量相同(我担心它必须通过一个函数的事实会减慢速度)。

以下是这两种不同循环方法所需的时间:

for(long i = 0 ; i < mylist.size(); i++){}
VS
for(long i = 0 ; i < 10_000_000; i++){}

这是一千万个元素列表的结果:

fixed length:
,162,157,151,157,156,159,157,149,150,170,158,153,152,158,151,151,156,156,151,153
getSize:
,164,156,159,154,151,160,162,152,154,152,151,149,168,156,152,150,157,150,156,157



import java.util.ArrayList;
import java.util.List;

public class Main {

    final static int LENGTH_SAMPLE = 20;
    final static long LENGTH = 10_000_000;

    public static void main(String[] args) {

        List<Long> mylist = new ArrayList<>();
        for(long i = 0 ; i < LENGTH; i++){
            mylist.add(i);
        }
        System.out.println("fixed length:");
        for(int i = 0 ; i < LENGTH_SAMPLE; i++){
            System.out.printf("," + fixedSize(mylist));
        }
        System.out.println("");
        System.out.println("getSize:");
        for(int i = 0 ; i < LENGTH_SAMPLE; i++){
            System.out.printf("," + fctSize(mylist));
        }
    }

    private static long fixedSize(List list){
        long start = System.currentTimeMillis();

        for(long i = 0 ; i < LENGTH; i++){
            System.currentTimeMillis();
        }
        return System.currentTimeMillis() - start;
    }

    private static long fctSize(List list){
        long start = System.currentTimeMillis();

        for(long i = 0 ; i < list.size(); i++){
            System.currentTimeMillis();
        }
        return System.currentTimeMillis() - start;
    }
}
于 2016-06-03T23:50:24.180 回答