假设我们有一个带有大量迭代的双循环,我们是否应该在循环外定义变量以加快速度?仅举例:
for(int i=0;i<2000;i++)
for(int j=0;j<1000;j++)
System.out.println(i+j);
因为我每次更改值时都会初始化j,所以最好将j声明为外部,例如:
for(int i=0;i<2000;i++){
int j=0;
for(j=0;j<1000;j++)
System.out.println(i+j);
}
对于我自己,我喜欢第一种方式,它更具可读性。但是,我不确定第二种方式是否会加快程序的速度?
答案 0 :(得分:1)
不,第二种形式在任何方面都不是更好(它甚至不会编译,因为你错过了for循环的init-section)!
for语句构建如下:for (init, expression, update) statement
init
语句将在循环之前执行ONCE
开始
expression
语句将在每次迭代之前执行
循环。只有当结果为true
时,循环才会继续。
update
语句将在每次迭代后立即执行。
statement
是将在每个中执行的语句
迭代。
所以它只是一个简短形式:
init;
while (expression) {
statement;
update;
}
由于init
只会被执行一次,如果你把它放在for
循环之前就没有优化。
答案 1 :(得分:1)
Javac生成的代码完全相同,因此没有任何区别:
给出“Test.java”文件:
public class Test {
public static int a(int[][] v) {
int sum = 0;
int rows = v.length;
int cols = v[0].length; // yes, this fails if v[0] is null
for (int j=0; j<rows; j++) {
for (int i=0; i<cols; i++) {
sum += v[j][i];
}
}
return sum;
}
public static int b(int[][] v) {
int sum = 0;
int rows = v.length;
int cols = v[0].length; // yes, this fails if v[0] is null
int j, i;
for (j=0; j<rows; j++) {
for (i=0; i<cols; i++) {
sum += v[j][i];
}
}
return sum;
}
}
编译(javac Test.java
)并查看类文件中的字节码(javap -c Test
的结果)。这是b
:
public static int b(int[][]);
Code:
0: iconst_0
1: istore_1
2: aload_0
3: arraylength
4: istore_2
5: aload_0
6: iconst_0
7: aaload
8: arraylength
9: istore_3
10: iconst_0
11: istore 4
13: iload 4
15: iload_2
16: if_icmpge 50
19: iconst_0
20: istore 5
22: iload 5
24: iload_3
25: if_icmpge 44
28: iload_1
29: aload_0
30: iload 4
32: aaload
33: iload 5
35: iaload
36: iadd
37: istore_1
38: iinc 5, 1
41: goto 22
44: iinc 4, 1
47: goto 13
50: iload_1
51: ireturn
答案 2 :(得分:0)
没有必要这样做。内置类型没有显着的设置成本。
事物与物体不同。
出于性能原因,您应该在循环外预先声明对象。我用JDK 1.4测试了这个,从那时起再也没有。可能更新的JDK会优化它。
for(int i=0;i<2000;i++)
for(int j=0;j<1000;j++)
String x = "Hello " + j;
明显慢于(定义外部循环)
String x;
for(int i=0;i<2000;i++)
for(int j=0;j<1000;j++)
x = "Hello " + j;
明显慢于(最终循环)
for(int i=0;i<2000;i++)
for(int j=0;j<1000;j++)
final String x = "Hello " + j;
更新:只使用JDK 7u45,1000 x 1000次迭代运行时间
我已将代码设置为多次运行循环并将变量保存在结果数组中。另一次运行不会将变量存储在循环之外。
循环中没有商店的字符串分配:平均43.5 / NoGC:39-47
循环外的字符串分配和数组存储:Avg 98.9 / NoGC:42-44
循环外的字符串分配,没有商店:平均28.25 / NoGC:27-32
循环中的最终字符串分配和数组存储:Avg 98.92 / NoGC:42-50
结果显示,对象的声明会造成损失。但真正的驱动力是GC。如果在循环外部使用该值,则循环内部或外部的声明效果会很小。在循环中使用最终的String将没有任何区别。 如果你不在循环之外存储,那么在循环内部或外部变量的声明之间的区别是显着的,最终,再次,没有区别。
(*存储所有值时,大部分时间都在GC运行中丢失,这就是我在没有GC的情况下添加运行范围的原因。)