1. 程式人生 > >foreach與Iterator的一些事

foreach與Iterator的一些事

1:foreach與Iterator

最近在閱讀Java程式設計思想第11章看到了Foreach與迭代器,文中說到“foreach語法主要用於陣列,但是它也可以應用於任何Collection物件,任何實現了Iterator介面的類,都可以將它用於foreach語句中”,其實Iterator就是告訴foreach如何在序列中移動元素,到底是每次向前移動一個元素還是向後移動一個元素具體看你如何實現的Iterator介面了,下面就是Iterator介面的方法,總共也就是三個,hasNext() next() 和 remove(),剛才說到的具體如何在序列中移動元素對應到就是如何實現的next()方法.

public interface Iterator<E> {

    boolean hasNext();

    E next();

    void remove();
}

2:foreach的本質

隱約記得foreach實則還是呼叫的Iterator,本著學習的目的想去檢視下foreach的原始碼卻發現並沒有,也看了不少類似的文章確實通過反編譯可以進行證實,這裡附上反編譯前後的方法對比

反編譯前

    public static void testForEach(List persons) {  
        Object curPerson;  
        for
(Object person : persons){ curPerson = person; } }

反編譯後

    public static void testForEach(List persons) {  
        for (Iterator iterator = persons.iterator(); iterator.hasNext();) {  
            Object person = iterator.next();  
            Object obj = person;  
        }  
    }  

從反編譯後的結果可以明顯看出foreach實則還是通過迭代器實現的,其實在編譯期就進行這步替換,即將foreach替換為Iterator。

3:效率

自己也是親自對兩種遍歷方式的效率進行了測試,主要還是使用了常用的ArrayList進行的測試。
測試的結果如下

量值 foreach遍歷耗時(ms) Iterator遍歷耗時(ms)
10000 5998 5377
100000 18743 16054
1000000 29426 22207

從測試的結果來看foreach的遍歷效能略低於Iterator

附:測試的原始碼,其中的Person為一簡單的實體類,僅包含String name和int age兩個屬性

        /*
         * System.nanoTime()獲取的時間單位為納秒
         */
        List<Person> persons = new ArrayList<Person>();
        for(int i=0;i<1000000;i++){
            persons.add(new Person("Muyi"+i,i));
        }
        System.out.println(persons.size());
        Person curPerson = null;
        long beginTime = System.nanoTime();
        for(Person person:persons){
            curPerson = person;
        }
        long currentTime = System.nanoTime();
        System.out.println("Foreach UseTime:"+(currentTime-beginTime)/1000);
        Iterator<Person> iterator = persons.iterator();
        beginTime = System.nanoTime();
        while(iterator.hasNext()){
            curPerson = iterator.next();
        }
        currentTime = System.nanoTime();
        System.out.println("Iterator UseTime:"+(currentTime-beginTime)/1000);