for循环之性能优化

前言

创新互联建站长期为近千家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为汝城企业提供专业的成都做网站、网站制作,汝城网站改版等技术服务。拥有10余年丰富建站经验和众多成功案例,为您定制开发。

for循环是开发时常用的语法之一,比如对数组,集合的遍历等,但是如果使用不好也会出现很多新能损耗的问题,今天就来讲解一下for循环的常用性能优化问题。

嵌套循环

嵌套循环是有俩层或者俩层以上的循环嵌套在一起,下面直接上代码说明。

外大内小嵌套:

/**

* 大循环驱动小循环(即外大内小)

*/

private static void bigSmall() {

long stratTime = System.nanoTime();

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

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

}

}

long endTime = System.nanoTime();

System.out.println("外大内小耗时:" + (endTime - stratTime));

}

执行看一下结果耗时:

外大内小耗时:8743800

再看看外小内大耗时情况

外小内大嵌套

/**

* 小循环驱动大循环(即外小内大)

*/

private static void smallBig() {

long stratTime = System.nanoTime();

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

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

}

}

long endTime = System.nanoTime();

System.out.println("外小内大耗时:" + (endTime - stratTime));

}

执行看一下结果耗时:

外小内大耗时:6922600

好了,综合比较一下俩者的执行时间,时差还是很大的。

外小内大耗时:6922600 ;外大内小耗时:8743800

总结:

由以上对比可知,优化后性能显著提升。嵌套循环应该遵循“外小内大”的原则,虽然循环次数没变,但是耗时却长了很大。这就好比你复制很多个小文件和复制几个大文件的区别,虽然总的大小没变,但是复制大文件明显比多个小文件更快。

循环变量的实例化

把循环变量的实例放在循环内:

/**

* 循环变量放在循环内

*/

private static void smallBigBetterTwo() {

long stratTime = System.nanoTime();

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

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

}

}

long endTime = System.nanoTime();

System.out.println("循环内变量耗时:" + (endTime - stratTime));

}

执行耗时:

循环内变量耗时:4934500

把循环变量的实例放在循环之外:

/**

* 循环变量放在循环外

*/

private static void smallBigBetter() {

long stratTime = System.nanoTime();

int i, j;

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

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

}

}

long endTime = System.nanoTime();

System.out.println("循环外变量耗时:" + (endTime - stratTime));

}

执行耗时:

循环外变量耗时:5013800

对比一下把变量放在循环内和循环外对比耗时,发现时差还是挺大的:

循环内变量耗时:4934500;循环外变量耗时:5013800

分析总结:

虽然优化效果并不明显,但是随着循环次数的增加,耗时会越来越大,优化效果则会越来越明显。分析:优化前需要实例化1+i=101次,优化后仅仅2次。总结:循环变量的实例化应放在循环外。

提取与循环无关的表达式

没有提取无关的表达式

/**

* 未提取无关的表达式

*/

private static void calculationInner() {

int a = 3;

int b = 7;

long stratTime = System.nanoTime();

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

i = i * a * b;

}

long endTime = System.nanoTime();

System.out.println("未提取耗时:" + (endTime - stratTime));

}

没有提取耗时:

未提取耗时:800

提取了无关的表达式

/**

* 提取无关的表达式

*/

private static void calculationOuter() {

int a = 3;

int b = 7;

int c = a * b;

long stratTime = System.nanoTime();

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

i = i * c;

}

long endTime = System.nanoTime();

System.out.println("已提取耗时:" + (endTime - stratTime));

}

提取了无关表达式耗时:

已提取耗时:500

分析总结:郑州妇科医院 https://yiyuan.120ask.com/zzfck/

代码中a*b与循环无关,所以应该把它放到外面,避免重复计算。从理论角度分析,由于减少了计算次数,故优化后性能会更高。

消除循环终止判断时的方法调用

stratTime = System.nanoTime();

for (int i = 0; i < list.size(); i++) {

}

endTime = System.nanoTime();

System.out.println("未优化list耗时:"+(endTime - stratTime));

耗时:

未优化list耗时:253800

优化后

stratTime = System.nanoTime();

int size = list.size();

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

}

endTime = System.nanoTime();

System.out.println("优化list耗时:"+(endTime - stratTime));

耗时:

优化list耗时:142500

分析总结:

每次循环,list.size()都会被执行一次,这无疑会影响程序的性能,所以应该将其放到循环外面,用一个变量来缓存其size,不要让这一点点代码而消耗我们这么多性能。

异常捕获

在内部捕获异常:

/**

* 在内部捕获异常

*/

private static void catchInner() {

long stratTime = System.nanoTime();

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

try {

} catch (Exception e) {

}

}

long endTime = System.nanoTime();

System.out.println("在内部捕获异常耗时:" + (endTime - stratTime));

}

执行耗时:

在内部捕获异常耗时:3352700

在外部捕获异常:

/**

* 在外部捕获异常

*/

private static void catchOuter() {

long stratTime = System.nanoTime();

try {

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

}

} catch (Exception e) {

}

long endTime = System.nanoTime();

System.out.println("在外部捕获异常耗时:" + (endTime - stratTime));

}

执行耗时:

在外部捕获异常耗时:2893600

分析总结:

捕获异常很占用资源,所以不要把try catch放到循环内部,优化后性能同样有好几个数量级的提升。另外, 《Effective Java》一书指出for-each循环优先于传统的for循环,它在简洁性和预防bug方面有着传统for循环无法媲美的优势,并且,没有性能方面的损失,因此,推荐使用for-each循环。


文章标题:for循环之性能优化
URL地址:http://hbruida.cn/article/gshsjj.html