在for循环中,每次迭代都会计算数组的长度吗?

时间:2015-01-14 00:20:53

标签: java

如果我有像...一样的for循环。

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

...每次迭代都会评估myArray.length吗?那就像... ...

int len = myArray.length;
for (int i = 0; i < len; i++) { ... }

......性能会有小幅提升吗?

4 个答案:

答案 0 :(得分:4)

无论myArray.length只是一个字段,因此无需评估

Java数组的长度为public final int,所以它被初始化一次,当你引用它时,没有像方法调用那样的代码执行

  

公共最终字段长度,包含数组的组件数。长度可以是positive or zero.

答案 1 :(得分:3)

第一种形式可能会产生一些性能损失,因为评估它需要在iflt之前,aloadarraylengthiload;而第二个只有两个iload s。

@ajp正确地提到myArray可能更改;所以编译器会高度不太可能将第一种形式优化为第二种形式(除非,myArray可能是final)。

然而,JIT,当它开始时,可​​能足够聪明,如果myArray没有改变,它将把第一个形式变成第二个。

以防万一,无论如何,使用第二种形式(这是我经常做的,但这只是出于习惯)。请注意,您始终可以javap生成的类文件来查看生成的字节代码并进行比较。


顺便说一句,维基百科有一个very handy page listing all of a JVM's bytecodes。正如您所看到的,其中很多都专注于阵列!

答案 2 :(得分:2)

是的,每次都会评估终止表达式。所以你保持一次长度可能是一个小的性能提升是正确的。但更重要的是,它改变了逻辑,如果重新分配myArray,这可能会有所不同。

for (int i = 0; i < myArray.length; i++) {
    if (something-something-something) {
        myArray = appendToMyArray(myArray, value);  // sets myArray to a new, larger array
    }
}

现在,首先将数组长度存储在变量中会产生很大的不同。

您通常不会看到带有数组的代码。但是对于arrayList或其他集合,其大小可以在循环体中增加(或减少),无论您是一次还是每次计算大小,都会产生差异。这个习惯用法出现在你保留“待办事项列表”的算法中。例如,这是一个部分算法,用于查找直接或间接与某人建立联系的所有人:

ArrayList<Person> listToCheck = new ArrayList<>(KevinBacon);
for (int i = 0; i < listToCheck.size(); i++) {
    List<Person> connections = allConnections(listToCheck.get(i));
    for (Person p : connections) {
        if ([p has not already been checked]) {
            listToCheck.add(p);  // increases listToCheck.size()!!!
        }
    }
}

答案 3 :(得分:0)

不是真的。两种情况都是将两个内存地址的值与每次迭代进行比较,除非您在使用len变量时进行不必要的分配。性能差异可能非常小,第一行更具可读性,因此我会使用第一种方式,因为它更具可读性。如果您想要更具可读性和效率,请使用for-each循环,如果您只是要通过数组进行线性迭代。 for-each循环看起来像这样:

int [] myArray = {1,2,3};
for(int i:myArray){
System.out.print(i);
}

将打印:

1
2
3

因为我被设置为数组的每个元素。 for each循环可用于许多对象,是一个很好的学习功能。 这是一本解释它的指南。

https://www.udemy.com/blog/for-each-loop-java/