在Java代碼中,除開需要對循環對象進行特殊操作(如remove、或需要知道當前index),一般碰到for循環我們總會下意識使用foreach;而這時不同的操作對象對性能的消耗卻有很大差別。
例如,比較一個簡單的遍歷:
{
int i=0;
for(String s:array){
i++;
}
}
其中array是一個容量1w的"容器"。
當選用不同的遍歷對象,對上述代碼重復1000次,消耗時間有很大差別:
1.array是一個數組String[10000] : 141 ms
2.array是一個HashSet<String> : 2354 ms
3.array是一個ArrayList<String> : 3413 ms
原因很簡單,在遍歷不同容器時,foreach的編譯方式各不相同,如查看ArrayList編譯後的class文件:
{
int i=0;
for (Iterator localIterator = array.iterator(); localIterator.hasNext(); ) {
String str = (String)localIterator.next();
++i;
}
}
程序運行時,首先需要用ArrayList創建一個新的迭代器對象Iterator,然後再進行常規for循環。
涉及創建新對象自然會產生額外的資源消耗。
因而,假設for中的遍歷對象(比如某些配置)在初始化之後很少變化,正確的做法是在初始化完成後將其轉換成數組,之後只對數組進行調用:
String[]array=list.toArray(new String[0]);
雖然是小技巧,但在需要頻繁調度的程序中,這很可能便是那額外的一個核CPU。 很多人傾向在Java中使用數組保存數據而不用容器,也正是基於這些原因。
另:在JDK1.7中Iterator性能已做優化,與按位遍歷持平,但仍低於數組。