1. 程式人生 > >Java中迭代列表中資料時幾種迴圈寫法的效率比較

Java中迭代列表中資料時幾種迴圈寫法的效率比較

Java中經常會用到迭代列表資料的情況,本文針對幾種常用的寫法進行效率比較。雖然網上已經有了類似的文章,但是對他們的結論並不認同。

常見的實現方法:

1.for迴圈:

for(int i = 0; i < list.size(); i++)
for(int i = 0, size = list.size(); i < size; i++)
一般人都會認為第二種寫法效率高。

2.foreach:

for(Object obj : list)

這是一種簡潔的寫法,只能對列表進行讀取,無法修改。

3.while:

int size = list.size();
while(size-- > 0)

4.迭代:
Object iter = list.iterator();
while(iter.hasNext()) {
  iter.next();
}

測試程式碼:

 針對以上幾種方法編寫的測試程式碼。
      public static void main(String[] args) {
            List<Integer> list = new ArrayList<Integer>();

            int runTime = 1000;//執行次數
            for (int i = 0; i < 1000 * 1000; i++) {
                list.add(i);
            }
            int size = list.size();
            long currTime = System.currentTimeMillis();//開始分析前的系統時間
            //基本的for            
            for(int j = 0; j < runTime; j++) {
                for (int i = 0; i < size; i++) {
                    list.get(i);
                }
            }
            long time1 = System.currentTimeMillis();

            //foreach
            for(int j = 0; j < runTime; j++) {
                for (Integer integer : list) {
                }
            }
            long time2 = System.currentTimeMillis();

            for(int j = 0; j < runTime; j++) {
                //while
                int i = 0 ;
                while(i < size){
                    list.get(i++);
                }
            }
            long time3 = System.currentTimeMillis();

            for(int j = 0; j < runTime; j++) {//普通for迴圈
                for (int i = 0; i < list.size(); i++) {
                    list.get(i);
                }
            }
            long time4 = System.currentTimeMillis();

            for(int j = 0; j < runTime; j++) {//迭代
                Iterator<Integer> iter = list.iterator();
                while(iter.hasNext()) {
                    iter.next();
                }
            }
            long time5 = System.currentTimeMillis();

            long time = time1 - currTime ;
            System.out.print("use for:" + time);
            time = time2 - time1;
            System.out.print("\tuse foreach:" + time);
            time = time3 - time2;
            System.out.print("\tuse while:" + time);
            time = time4 - time3;
            System.out.print("\tuse for2:" + time);
            time = time5 - time4;
            System.out.print("\tuse iterator:" + time);
            System.out.println();
        }

輸出結果(JDK1.6):

1.

use for:8695        use foreach:17091        use while:6867        use for2:7741        use iterator:14144

2.

use for:8432        use foreach:18126        use while:6905        use for2:7893        use iterator:13976

3.

use for:8584        use foreach:17177        use while:6875        use for2:7707        use iterator:14345

結論:

1.針對列表的 foreach的效率是最低:

耗時是普通for迴圈的2倍以上。個人理解它的實現應該和iterator相似。

2. list.size()的開銷很小:

list.size()次數多少對效率基本沒有影響。檢視ArrayList的實現就會發現,size()方法的只是返回了物件內的長度屬性,並沒有其它計算,所以只存在函式呼叫的開銷。

對陣列的測試:

將程式碼中的列表list換做陣列再進行測試(iterator不適用),發現耗時基本為0。說明:
3. 列表的get()方法開銷不少

應該主要是檢測資料合法性時產生的。

將執行次數增加100萬倍,這時可以看出結果基本相等,並沒有明顯的差異。說明:

4. 陣列length也沒有開銷

可見陣列長度並不是每次執行的時候都要計算的。聯想一下Java建立陣列的時候要求必須指定陣列的長度,編譯處理的時候顯然沒有把這個值拋棄掉。

網上有一篇類似的文章,它居然得出了一個foreach執行效率最高的結論。看一下它的測試程式碼就會發現一個要命的問題,它居然在執行每次迴圈的時候呼叫了System.out.print()方法將陣列內容輸出,難道他不知道這個操作耗時非常大嗎,這樣計算出的結果有什麼用處呢。