java多重循环如何优化_Java中多重循环的优化问题

for (int i = 0; i < 1000; i++) {

for (int j = 0; j < 100; j++) {

for (int k = 0; k < 10; k++) {

System.out.print(i * j * k);

}

}

} // 代码1

for (int i = 0; i < 10; i++) {

for (int j = 0; j < 100; j++) {

for (int k = 0; k < 1000; k++) {

System.out.print(i * j * k);

}

}

} // 代码2

// 代码2比代码1优化,具体的原因是什么。其实这个问题,sunandice的解释是正确的:

// 由于将int

// j=0写在for语句里面,因此,j的作用域只局限在当前的for循环里面。出循环后,j就不存在了。要再进入for循环,需要再次为变量j分配空间。前面的代码,变量i要声明和初始化1次,变量j要声明和初始化1000次,变量k要声明和初始化100000次。后面的代码,变量i要声明和初始化1次,变量j要声明和初始化10次,变量k要声明和初始化1000次。还可以将上面的代码优化成:

int i, j, k;

for (i = 0; i < 10; i++) {

for (j = 0; j < 100; j++) {

for (k = 0; k < 1000; k++) {

System.out.print(i * j * k);

}

}

} // 代码3

为了说明方便,我们把这三段代码按照出现顺序编为代码1,代码2,代码3。我们可以使用

System.currentTimeMillis();方法获取当前时间,比较代码执行前后的时间。下面是代码

public class Test1 {

public static void main(String[] args){ long begin=System.currentTimeMillis(); int i,j,k; for (i = 0; i < 1000; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 10; k++) { System.out.println(i * j * k); } } } long end=System.currentTimeMillis(); System.out.println("Test1time="+(end-begin)); }}

我们分别对三段代码进行测试,发现代码1执行时间156953ms,代码2时间140640ms,代码3时间129438ms,

其中代码2比较代码1快了16.3s,而代码3比代码2快11.2s。

对于这样的多重循环,如果里面包含语句,我们都可以从循环次数判断出代码2比代码1少执行了指令。

如下所示,代码2比代码1少执行(100*1000-10)条打印语句。

for(int i=0;i<1000;i++){ System.out.print(i); //执行1000 for(int j=0;j<100;j++){ System.out.print(j); //执行 100*1000 for(int k=0;k<10;k++){ System.out.print(i*j*k); //执行1000*100*10 } }} //代码1

for(int i=0;i<10;i++){ System.out.print(i); //执行10 for(int j=0;j<100;j++){ System.out.print(j); //执行 10*100 for(int k=0;k<1000;k++){ System.out.print(i*j*k); //执行10*100*1000 } }} //代码2

但是对于原始的多重循环,好像只有里面包含了一个打印语句。代码1和代码2执行的打印语句一样多都是

10*100*1000条。

其实,当我们的Java文件编译成class文件后,我们会发现一条高级语言的语句,可能变成了多条JVM指令。

我们可以通过JDK自带的命令 javap -c Test1来分析类文件的指令。我们可以看到for循环中的变量声明、

赋值语句、比较语句、++语句这些都会转换成进栈、出栈、比较、加等各种指令。也就是说代码1比代码2会

多执行很多JVM指令,同理代码2也会比代码3多执行很多JVM指令(因为一个简单的int i,int j之类的变量

声明,编译成JVM指令后,可不只是一条指令)。把代码1和代码2的JVM指令附在下面,有兴趣的可以自己研究。

JVM指令可以参考:http://thinkinmylife.javaeye.com/blog/443900。

代码1:Compiled from "Test1.java"public class Test1 extends java.lang.Object{public Test1(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: iconst_0 1: istore_1 2: iload_1 3: sipush 1000 6: if_icmpge 54 9: iconst_0 10: istore_2 11: iload_2 12: bipush 100 14: if_icmpge 48 17: iconst_0 18: istore_3 19: iload_3 20: bipush 10 22: if_icmpge 42 25: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 28: iload_1 29: iload_2 30: imul 31: iload_3 32: imul 33: invokevirtual #3; //Method java/io/PrintStream.print:(I)V 36: iinc 3, 1 39: goto 19 42: iinc 2, 1 45: goto 11 48: iinc 1, 1 51: goto 2 54: return}

代码2:Compiled from "Test2.java"public class Test2 extends java.lang.Object{public Test2(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: iconst_0 1: istore_1 2: iload_1 3: bipush 10 5: if_icmpge 54 8: iconst_0 9: istore_2 10: iload_2 11: bipush 100 13: if_icmpge 48 16: iconst_0 17: istore_3 18: iload_3 19: sipush 1000 22: if_icmpge 42 25: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 28: iload_1 29: iload_2 30: imul 31: iload_3 32: imul 33: invokevirtual #3; //Method java/io/PrintStream.print:(I)V 36: iinc 3, 1 39: goto 18 42: iinc 2, 1 45: goto 10 48: iinc 1, 1 51: goto 2 54: return}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值