1. 程式人生 > >ArrayList三種遍歷方式比較

ArrayList三種遍歷方式比較

方法一:普通for迴圈遍歷

//僅做程式碼的格式說明,不涉及具體問題
for(int i = 0 ; i < list.size() ; i++){ 
   system.out.println(list.get(i)); 
}

方法二:增強for迴圈遍歷

增強for迴圈的底層也是Iterator實現的,只是對它包裝了一下。

for(String string:list){ 
   system.out.println(string); 
}

方法三:Iterator迭代器遍歷

Iterator it = list.iterator();
 while(it.hasNext()) {
 System.out.println(it.next());
 }

這三種方式哪一種效率最高呢?讓我們來測試一下:

//測試程式碼,三種方式遍歷8000000條資訊
public class ArrayListTest {
    private static List<String> list = new ArrayList<String>();

    public static void main(String[] args) {
        ArrayListTest test = new ArrayListTest();
        test.initList(list);
        test.forList(list);
        test.forEachList(list);
        test.iteratorList(list);

    }

    //在List裡面新增8000000條資訊
public List<String> initList(List<String> list){ int num = 8000000; for(int i = 0; i < num; i++){ list.add("ListTest"+i); } return list; } //普通for迴圈遍歷 public void forList(List<String> list){ long start = System.currentTimeMillis(); for
(int i = 0; i < list.size(); i++){ String value = list.get(i); } long end = System.currentTimeMillis(); long usedTime = end - start; System.out.println("普通for迴圈遍歷時間:"+usedTime); } //增強for迴圈遍歷 public void forEachList(List<String> list){ long start = System.currentTimeMillis(); for(String string:list){ String value = string; } long end = System.currentTimeMillis(); long usedTime = end - start; System.out.println("增強for迴圈遍歷時間:"+usedTime); } //Iterator迭代器遍歷 public void iteratorList(List<String> list){ long start = System.currentTimeMillis(); Iterator<String> it = list.iterator(); while(it.hasNext()){ String value = (String) it.next(); } long end = System.currentTimeMillis(); long usedTime = end - start; System.out.println("Iterator迭代器遍歷時間:"+usedTime); } }

在做同樣操作的情況下,結果相當隨機,並沒有明顯的差別,測試結果如下

普通for迴圈遍歷時間:109
增強for迴圈遍歷時間:114
Iterator迭代器遍歷時間:107
普通for迴圈遍歷時間:90
增強for迴圈遍歷時間:90
Iterator迭代器遍歷時間:93
普通for迴圈遍歷時間:88
增強for迴圈遍歷時間:85
Iterator迭代器遍歷時間:92

但是,如果只遍歷,不做其他操作,差別非常明顯,測試結果如下

普通for迴圈遍歷時間:6
增強for迴圈遍歷時間:116
Iterator迭代器遍歷時間:12
普通for迴圈遍歷時間:6
增強for迴圈遍歷時間:98
Iterator迭代器遍歷時間:14
普通for迴圈遍歷時間:5
增強for迴圈遍歷時間:83
Iterator迭代器遍歷時間:15

耗時最短是傳統的for迴圈,其次是iterator、增強for迴圈,也就是按下標遍歷的方式的效能要高於迭代的方式。增強for迴圈的底層實現原理就是迭代器Iterator。如果是順序訪問下標的那些類例項,使用for迴圈去遍歷。

在官方API文件中找到了說明,在遍歷ArrayList時,普通for迴圈要比iterator快,以下摘自API:

public interface RandomAccess
Marker interface used by List implementations to indicate that they support fast (generally constant time) random access. The primary purpose of this interface is to allow generic algorithms to alter their behavior to provide good performance when applied to either random or sequential access lists.
The best algorithms for manipulating random access lists (such as ArrayList) can produce quadratic behavior when applied to sequential access lists (such as LinkedList). Generic list algorithms are encouraged to check whether the given list is an instanceof this interface before applying an algorithm that would provide poor performance if it were applied to a sequential access list, and to alter their behavior if necessary to guarantee acceptable performance.

It is recognized that the distinction between random and sequential access is often fuzzy. For example, some List implementations provide asymptotically linear access times if they get huge, but constant access times in practice. Such a List implementation should generally implement this interface. As a rule of thumb, a List implementation should implement this interface if, for typical instances of the class, this loop:

     for (int i=0, n=list.size(); i < n; i++)
         list.get(i);

runs faster than this loop:
     for (Iterator i=list.iterator(); i.hasNext(); )
         i.next();

This interface is a member of the Java Collections Framework.

Since:
1.4