java性能優化筆記 —— for循環

1.多層嵌套循環

stratTime = System.nanoTime();  
for (int i = 0; i <10000 ; i++) {  
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 10; k++) {  
            testFunction(i, j, k);
        }
    }
}
System.out.println("外大內小耗時:"+ (endTime - stratTime));

優化後:性能

stratTime = System.nanoTime();  
for (int i = 0; i <10 ; i++) {  
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 10000; k++) {  
            testFunction(i, j, k);
        }
    }
}
endTime = System.nanoTime();  
System.out.println("外小內大耗時:"+(endTime - stratTime));

二者耗時對比:優化

外大內小耗時:1582127649  
外小內大耗時:761666633

優化原理

咱們先分析原代碼循環變量在實例化、初始化、比較、自增等方面的耗時狀況:code

優化前:資源

變量 實例化(次數) 初始化(次數) 比較(次數) 自增(次數)
i 1 1 10000 10000
j 10000 10000 10000*100 10000*100
k 10000*100 10000*100 1000010010 1000010010

優化後:io

變量 實例化(次數) 初始化(次數) 比較(次數) 自增(次數)
i 1 1 10 10
j 10 10 10*100 10*100
k 10*100 10*100 1010010000 1010010000

結論

嵌套循環應該遵循「外小內大」的原則table


2.循環變量的實例化應放在循環外

在1.中優化後的代碼基礎上,進行二次優化:test

stratTime = System.nanoTime();  
int i, j, k;
for (i = 0; i <10 ; i++) {  
    for (j = 0; j < 100; j++) {
        for (k = 0; k < 10000; k++) {  
            testFunction(i, j, k);
        }
    }
}
endTime = System.nanoTime();  
System.out.println("提取出循環內變量後耗時:"+(endTime - stratTime));

結果以下:基礎

外小內大耗時:761666633  
 提取出循環內變量後耗時:748479323

優化並不明顯,可是當循環越大時,耗時會差距更大變量

## 優化原理
優化後:原理

變量 實例化(次數) 初始化(次數) 比較(次數) 自增(次數)
i 1 1 10 10
j 1 10 10*100 10*100
k 1 10*100 1010010000 1010010000

結論

循環變量的實例化應該儘可能放在循環外進行


3.提取與循環無關的表達式

stratTime = System.nanoTime();  
for (int i = 0; i < 10000000; i++) {  
    i=i*a*b;  
}  
endTime = System.nanoTime();  
System.out.println("未提取耗時:"+(endTime - stratTime));

優化後:

stratTime = System.nanoTime();  
c = a*b;  
for (int i = 0; i < 10000000; i++) {  
    i=i*c;  
}  
endTime = System.nanoTime();  
System.out.println("已提取耗時:"+(endTime - stratTime));

結論:

代碼中a+b與咱們的循環無關,因此應該把它放到外面,避免重複計算。

4.消除循環終止判斷時的方法調用

stratTime = System.nanoTime();  
for (int i = 0; i < list.size(); i++) {  
      
}  
endTime = System.nanoTime();  
System.out.println("未優化list耗時:"+(endTime - stratTime));

優化後:

stratTime = System.nanoTime();  
int size = list.size();  
for (int i = 0; i < size; i++) {  
      
}  
endTime = System.nanoTime();  
System.out.println("優化list耗時:"+(endTime - stratTime));

結論

list.size()每次循環都會被執行一次,這無疑會影響程序的性能,因此應該將其放到循環外面,用一個變量來代替。


5.異常捕獲

stratTime = System.nanoTime();  
for (int i = 0; i < 10000000; i++) {  
    try {  
    } catch (Exception e) {  
    }  
}  
endTime = System.nanoTime();  
System.out.println("在內部捕獲異常耗時:"+(endTime - stratTime));

優化後:

stratTime = System.nanoTime();  
try {  
    for (int i = 0; i < 10000000; i++) {  
    }  
} catch (Exception e) {  
  
}  
endTime = System.nanoTime();  
System.out.println("在外部捕獲異常耗時:"+(endTime - stratTime));

結論

捕獲異常是很耗資源的,因此不要講try catch放到循環內部。

相關文章
相關標籤/搜索