`

循环的优化

    博客分类:
  • java
阅读更多
 循环的优化 
 ---------------------------------------
 1,数字比较尽量和0比较
 注释:计算机喜欢0和1
 //foo
 for(int i=0;i<Integer.MAX_VALUE;i++){
     //慢
 }
 //优化
 for(int i=Integer.MAX_VALUE;i>0;i--){
     //快
 }

 2,尽量把异常捕获写在外面
 //foo
 for(int i=180000;i>=0;i--){
 try{
 //慢
 }catch{
 }
 }

 //优化
 try{
 for(int i=180000;i>=0;i--){
 //快

 }
 }catch{
 }
 ---------------------------------------
 3,尽量不要在循环内有多余的方法调用
 //注释:除了方法调用本身耗费资源外,其方法内代码体的多次执行根据实际情况影响性能和内存,调用一次能解决问题就别调用两次
 for(int i=0;i>=IntMethod();i--){

 }
 //优化
 int len = IntMethod():
 for(int i=0;i>=len;i--){

 }


 ---------------------------------------
 4, 在循环中最好不要拼接字符串一
 注释:String是不变类,对其更改都会重新创建字符串,从而导致内存和速

度的问题,
 另外StringBuilder是sun为解决字符串操作效率低下而创建
地(StringBuffer早),
 有字符buffer,解决字符的增删改都是相当快滴
 //foo
 String str = "";
 for (int i = 0; i >= 18000; i--) {
     // 慢 占用内存大
     str += "慢 占用内存大";
 }
 //优化
 StringBuilder yourString = new StringBuilder();
 for (int i = 0; i >= 18000; i--) {
     // 快 占用内存小
     yourString.append("快 占用内存小");
 }
 ---------------------------------------
 5, 在循环中最好不要拼接字符串之二
 注释:看编译后代码,一目了然
 //foo
 StringBuilder yourString = new StringBuilder();
 for (Integer i = 0; i >= 18000; i--) {
     yourString.append("" + i);
 }
 // 优化
 for (Integer i = 0; i >= 18000; i--) {
     yourString.append(i.toString());
 }
 //编译后代码         注:经过处理
 /*
 //foo
 StringBuilder yourString = new StringBuilder();
 for (Integer i = Integer.valueOf(0); i.intValue() >= 18000; i = 

Integer.valueOf(i.intValue() - 1))
     yourString.append((new StringBuilder()).append(i).toString());
 // 优化
 for (Integer i = Integer.valueOf(0); i.intValue() >= 18000; i = 

Integer.valueOf(i.intValue() - 1))
     yourString.append(i.toString());
 */
分享到:
评论
23 楼 ccxw1983 2008-10-30  
如果是一个系统需要立即优化性能,马上投入生产环境,当然是抓主要的东西去优化。
但是平时编程,应该从细节去做到优化。否则平时积累的多了,整体影响会很大的。
22 楼 paranoid945 2008-10-29  
有了瓶颈了或者可以预测到瓶颈了才去优化它。
21 楼 sunflowers 2008-10-29  
BenoWay 写道

是不是我写的测试有问题呀。


你写的测试代码非常好,

不好的是,

for(int i=Integer.MAX_VALUE;i>=0;i--)

你少了一个等号,

我使用你的测试代码测试结果如下
开始测试for循环
5015
4767
开始测试for循环
5007
4829
开始测试for循环
4995
4794
开始测试for循环
4991
4786
开始测试for循环
4990
4920
开始测试for循环
4994
4786
开始测试for循环
5016
4759
开始测试for循环
4991
4882
开始测试for循环
4998
4802
开始测试for循环
20 楼 rinniclyks 2008-10-29  
这些细节以前还真没注意过呢
19 楼 96127 2008-10-29  
4, 在循环中最好不要拼接字符串一 
注释:String是不变类,对其更改都会重新创建字符串,从而导致内存和速 
 
度的问题, 
另外StringBuilder是sun为解决字符串操作效率低下而创建 
地(StringBuffer早), 
有字符buffer,解决字符的增删改都是相当快滴 
//foo 
String str = ""; 
   for (int i = 0; i >= 18000; i--) {    
     // 慢 占用内存大 
     str += "慢 占用内存大"; 

//优化 
StringBuilder yourString = new StringBuilder(); 
for (int i = 0; i >= 18000; i--) {
     // 快 占用内存小 
     yourString.append("快 占用内存小"); 


for (int i = 0; i >= 18000; i--) 改为
for (int i = 18000; i >= 0; i--)
18 楼 BenoWay 2008-10-29  
在for循环理更令人震惊,结果和楼主刚好相反:

import java.util.concurrent.TimeUnit;

/* 循环的优化   
---------------------------------------  
1,数字比较尽量和0比较  
注释:计算机喜欢0和1 
//foo  
for(int i=0;i<Integer.MAX_VALUE;i++){  
     //慢  
}  
//优化  
for(int i=Integer.MAX_VALUE;i>=0;i--){  
     //快  
}  
测试结论:看不太出来
*/

public class TestFor {

public TestFor(){
System.out.println("开始测试for循环");
}
//test from 0;
public void doForBegin0(){
for(long i=0;i<Integer.MAX_VALUE;i++){
;
}
}

//test from max
public void doForBeginMax(){
for(long i=Integer.MAX_VALUE;i>0;i--){
;
}
}


public static void main(String args[]){
for(int i=20;i>0;i--){
TestFor test = new TestFor();

long beginTime = System.currentTimeMillis();
test.doForBegin0();
long endTime = System.currentTimeMillis();
System.out.println(endTime-beginTime);

//System.runFinalization();
System.gc();
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}

beginTime = System.currentTimeMillis();
test.doForBeginMax();
endTime = System.currentTimeMillis();
System.out.println(endTime-beginTime);

}
  }
}

结果:每个都比第一种慢。。。。。》》》》》》》》
开始测试for循环
12531
13735
开始测试for循环
11297
11500
开始测试for循环
11235
11484
开始测试for循环
11250
11516
开始测试for循环
11281
11578
开始测试for循环
11250
11469
开始测试for循环
11203
11500
开始测试for循环
11250
11516
开始测试for循环
11296
11453
开始测试for循环
11235
11484
开始测试for循环
11250
11516
开始测试for循环
11281
11516
开始测试for循环
11281
11516
开始测试for循环
11375
11500
开始测试for循环
11297
11563
开始测试for循环
11312
11578
开始测试for循环
11282
11625
开始测试for循环
11266
11469
开始测试for循环
11640
11813
开始测试for循环
11234
11547

。。。。。
17 楼 BenoWay 2008-10-29  
是不是我写的测试有问题呀。
16 楼 zouzou 2008-10-29  
挺是不错的
15 楼 BenoWay 2008-10-29  
<p>/*循环的优化    <br/>---------------------------------------   <br/>1,数字比较尽量和0比较   <br/>注释:计算机喜欢0和1  <br/>//foo   <br/>for(int i=0;i&lt;Integer.MAX_VALUE;i++){   <br/>     //慢   <br/>}   <br/>//优化   <br/>for(int i=Integer.MAX_VALUE;i&gt;=0;i--){   <br/>     //快   <br/>}   <br/>*/ </p>
<p><br/>public class TestFor { <br/>private long count = 0; <br/><br/>public TestFor(long count){ <br/>System.out.println("开始测试for循环"); <br/>this.count = count; <br/>} <br/>//connect string <br/>public String connectBuilder(String str1,String str2,String str3){ <br/>StringBuilder builder = new StringBuilder(); <br/>return builder.append(str1). <br/>   append(str2). <br/>   append(str3). <br/>   toString(); <br/>} <br/>//test from 0; <br/>public void doForBegin0(){ <br/>for(long i=0;i&lt;count;i++){ <br/>connectBuilder("str1","str2","str3"); <br/>} <br/>} <br/><br/>//test from max <br/>public void doForBeginMax(){ <br/>for(long i=count;i&gt;0;i--){ <br/>connectBuilder("str1","str2","str3"); <br/>} <br/>} <br/><br/><br/>public static void main(String args[]){ </p>
<p> for(int i=20;i&gt;0;i--){ <br/><br/>TestFor test = new TestFor(10000000); <br/>long beginTime = System.currentTimeMillis(); <br/>test.doForBegin0(); <br/>long endTime = System.currentTimeMillis(); <br/>System.out.println(endTime-beginTime); <br/><br/>System.runFinalization(); <br/>System.gc(); <br/>try { <br/>TimeUnit.MILLISECONDS.sleep(1000); <br/>} catch (InterruptedException e) { <br/>e.printStackTrace(); <br/>} <br/><br/>beginTime = System.currentTimeMillis(); <br/>test.doForBeginMax(); <br/>endTime = System.currentTimeMillis(); <br/>System.out.println(endTime-beginTime); <br/> } <br/><br/>} <br/>} <br/><br/>/* <br/>测试结果:似乎好像看不太出来。。。。。。。》》》》》》》》》》》》》 </p>
<p><br/>开始测试for循环<br/>297<br/>281<br/>开始测试for循环<br/>266<br/>265<br/>开始测试for循环<br/>282<br/>282<br/>开始测试for循环<br/>265<br/>281<br/>开始测试for循环<br/>266<br/>265<br/>开始测试for循环<br/>282<br/>281<br/>开始测试for循环<br/>281<br/>282<br/>开始测试for循环<br/>281<br/>281<br/>开始测试for循环<br/>281<br/>281<br/>开始测试for循环<br/>265<br/>281<br/>开始测试for循环<br/>281<br/>281<br/>开始测试for循环<br/>282<br/>281<br/>开始测试for循环<br/>281<br/>282<br/>开始测试for循环<br/>265<br/>282<br/>开始测试for循环<br/>281<br/>281<br/>开始测试for循环<br/>282<br/>281<br/>开始测试for循环<br/>266<br/>266<br/>开始测试for循环<br/>281<br/>282<br/>开始测试for循环<br/>265<br/>282<br/>开始测试for循环<br/>281<br/>281<br/>*/</p>
<p> </p>
14 楼 lpp333 2008-10-28  
恩,楼主总结的非常好。
我们的编码规范也是这么要求的
13 楼 lirig 2008-10-28  
第一例子我觉得到差别不大,其他的是应该这样写,还有个那个异常处理也有问题,因为产生的结果不一样,那得根据业务需要了!平时编码时还是时要注意优化和美观!
12 楼 yufei 2008-10-28  
引用

2,尽量把异常捕获写在外面  
//foo  
for(int i=180000;i>=0;i--){  
try{  
//慢  
}catch{  
}  
}  
 
//优化  
try{  
for(int i=180000;i>=0;i--){  
//快  
 
}  
}catch{  
}  


这两个表示的意义都不一样
11 楼 willpower 2008-10-28  
lyy5271 写道
我觉得这些东西可以扩展知识面,但用处不大。
举个例子,访问二维数组的时候按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有什么用处。


当数据量大到一定程度时你就知道有不有用了。
10 楼 sunflowers 2008-10-28  
WhisperXD 写道
sunflowers 写道
lyy5271 写道

我觉得这些东西可以扩展知识面,但用处不大。举个例子,访问二维数组的时候按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有什么用处。


不敢苟同!如果仅仅是类似我文章类似1的优化,你的观点是正确的,

但是对于类似很多以下几个的优化,你的观点确实应该值得每一个认为无所为的程序员深思。

我们是写程序的,写出优秀的代码应该是我们共同的目标,不应当因系统的规模大小和难易程

度而改变我们的追求。当你看别人程序的时候,一个有很多年java开发经验的时候,你也许会

发现类似这样的拙劣:var.equals("123");,也许这样写是小事,可是我觉得这样写对于初学者

是可以原谅的……。回过头来看345,如果是企业应用,你的代码也许正在严重影响性能

一句话总结:无论你写的是什么样系统,都应该把你最好的代码写进去。



我觉得还是应该重申代码优化的核心理念,也就是先完成功能,进行性能测试,如果有问题才去优化,在大部分情况下,影响关键性能的都不是你认为他可能会影响性能的部分。所以这样的优化只是在对性能要求极其苛刻并且有充分的测试和编码时间的情况下才会去考虑的吧?^_^


WhisperXD 写道
sunflowers 写道
lyy5271 写道

我觉得这些东西可以扩展知识面,但用处不大。举个例子,访问二维数组的时候

按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机

的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有

什么用处。


不敢苟同!如果仅仅是类似我文章类似1的优化,你的观点是正确的,

但是对于类似很多以下几个的优化,你的观点确实应该值得每一个认为无所为的

程序员深思。

我们是写程序的,写出优秀的代码应该是我们共同的目标,不应当因系统的规模

大小和难易程

度而改变我们的追求。当你看别人程序的时候,一个有很多年java开发经验的时

候,你也许会

发现类似这样的拙劣:var.equals("123");,也许这样写是小事,可是我觉得这样

写对于初学者

是可以原谅的……。回过头来看345,如果是企业应用,你的代码也许正在严重影

响性能

一句话总结:无论你写的是什么样系统,都应该把你最好的代码写进去。


我觉得还是应该重申代码优化的核心理念,也就是先完成功能,进行性能测试,

如果有问题才去优化,在大部分情况下,影响关键性能的都不是你认为他可能会

影响性能的部分。所以这样的优化只是在对性能要求极其苛刻并且有充分的测试

和编码时间的情况下才会去考虑的吧?^_^


"我觉得还是应该重申代码优化的核心理念,也就是先完成功能",这句话我很赞同

,我想也许你误会我的意思,

我说的优化并不是指对已经完成的项目或者正在做项目的时候花费大量的时间去考虑

怎样写才是最优代码,我的意思是做项目的时候,经验所及的条件下写出自己最优的代码,

或者平常吸取他人的经验,留意自己代码的质量,提高自己的水平,而不是刻意的对未完成的系统或者已经完成的系统

,性能并不是瓶颈的时候去优化。

在做东西的时候应该像你说的那样:代码优化的核心理念,也就是先完成功能,进行性能测试。优化是在对性能要求苛

刻并且有充分的测试是才去考虑(Bruce Eckel好像也说过类似的话哦,呵呵)








9 楼 WhisperXD 2008-10-28  
sunflowers 写道
lyy5271 写道

我觉得这些东西可以扩展知识面,但用处不大。举个例子,访问二维数组的时候按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有什么用处。


不敢苟同!如果仅仅是类似我文章类似1的优化,你的观点是正确的,

但是对于类似很多以下几个的优化,你的观点确实应该值得每一个认为无所为的程序员深思。

我们是写程序的,写出优秀的代码应该是我们共同的目标,不应当因系统的规模大小和难易程

度而改变我们的追求。当你看别人程序的时候,一个有很多年java开发经验的时候,你也许会

发现类似这样的拙劣:var.equals("123");,也许这样写是小事,可是我觉得这样写对于初学者

是可以原谅的……。回过头来看345,如果是企业应用,你的代码也许正在严重影响性能

一句话总结:无论你写的是什么样系统,都应该把你最好的代码写进去。



我觉得还是应该重申代码优化的核心理念,也就是先完成功能,进行性能测试,如果有问题才去优化,在大部分情况下,影响关键性能的都不是你认为他可能会影响性能的部分。所以这样的优化只是在对性能要求极其苛刻并且有充分的测试和编码时间的情况下才会去考虑的吧?^_^
8 楼 sunflowers 2008-10-28  
lyy5271 写道

我觉得这些东西可以扩展知识面,但用处不大。举个例子,访问二维数组的时候按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有什么用处。


不敢苟同!如果仅仅是类似我文章类似1的优化,你的观点是正确的,

但是对于类似很多以下几个的优化,你的观点确实应该值得每一个认为无所为的程序员深思。

我们是写程序的,写出优秀的代码应该是我们共同的目标,不应当因系统的规模大小和难易程

度而改变我们的追求。当你看别人程序的时候,一个有很多年java开发经验的时候,你也许会

发现类似这样的拙劣:var.equals("123");,也许这样写是小事,可是我觉得这样写对于初学者

是可以原谅的……。回过头来看345,如果是企业应用,你的代码也许正在严重影响性能

一句话总结:无论你写的是什么样系统,都应该把你最好的代码写进去。

7 楼 lyy5271 2008-10-27  
我觉得这些东西可以扩展知识面,但用处不大。
举个例子,访问二维数组的时候按行优先比按列优先效率要高,原因是所谓的局部性原理,可以充分利用计算机的高速缓存,可是这些东西对做java的企业应用有什么用处呢?反正我觉得没有什么用处。
6 楼 sunflowers 2008-10-24  

对于1的可读性确实不是很好,在循环Integer.MAX_VALUE后差别也是几百毫秒,实际运用中也许没人写这样的代码,

但是它确实可以优化性能,我们要认识这一点,知道为什么,我们要从美观和性能之间选择一个,说一段多余的话:

美观其实大部分是因为用的人多,看习惯了,对吗?哪个好,个人爱好啦

2,对于异常在循环内还是在外,比较建议的是:能放在外面就放在外面,异常也是代码更何况他的速度和JIT有暧昧。

345这里就不说了,如果看看我写的例子,想一想,应该不会很难理解。

为什么我不写测试数据?只是觉得复制粘贴特别简单,修修改改,然后就可运行。另外,这个博客是我个人写的一些总结,

结和个人的观点认识,积累一下,以后也方便查阅,并回想当时的认识,没想到这么多人观看评论,如果有什么不同观点,愿请赐教,嘻嘻









5 楼 尔今尔后 2008-10-23  
恩。这个只要开发经验多了 就知道效率问题了。但是底层的原理还是讲解一下比较好。
4 楼 Element&lina 2008-10-23  
编译,然后反编译,熟悉字节码就知道怎样去优化你的代码,所谓的这些个技巧太多了,关键应该明白原理。

相关推荐

Global site tag (gtag.js) - Google Analytics