Java迭代器Iterator

來源:互聯網
上載者:User

標籤:java

之前我們實現了迭代器模式,很多程式設計語言實際上已經內建了迭代器類,比如Java就為我們實現了迭代器Iterator。我們首先來看Iterator中的源碼。

通過JDK源碼我們發現Iterator是一個介面,包含三個方法:hasNext、next、remove。

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

 1 package java.util; 2  3 public interface Iterator<E> { 4  5     /** 6     *如果迭代器中還有元素則返回true 7     */ 8     boolean hasNext(); 9 10     /**11     *返回迭代器中的下一個元素12     */13     E next();14 15     /**16     *通過迭代器刪除處於集合中最底層的元素17     */18     void remove();19 }

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

Iterator是一個介面,那如何來建立一個執行個體呢?要記住,迭代器和集合類的關係非常緊密,我們可以通過集合類來建立一個Iterator執行個體,ArrayList、LinkedList、Vector都有對它的實現。我們來看ArrayList是如何建立一個Iterator迭代器執行個體的。在此之前我們先來看看集合和迭代器之間的繼承關係。

650) this.width=650;" src="http://images2015.cnblogs.com/blog/630246/201609/630246-20160930000425344-1253264643.png" style="margin:0px;padding:0px;border:0px;width:686px;" />

由於集合的關係相對來說比較複雜,在此我們主要看注釋部分,通過閱讀原始碼會發現ArrayList覆寫了AbstractList抽象類別中的iterator方法並聲稱效果更佳,而LinkedList則沒有覆寫,由此可判斷ArrayList的iterator方法比LinkedList中的iterator方法更為高效。

我們直接看ArrayList裡中實現的iterator方法。

1 public Iterator<E> iterator() {2     return new Itr();3 }

從代碼來看它返回類一個Itr的對象執行個體,順著代碼看看這個Itr類是什麼。

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

 1 private class Itr implements Iterator<E> { 2     int cursor;       // 返回下一個元素的索引 3     int lastRet = -1; // 返回最後一個元素的索引;如果沒有則返回-1 4     int expectedModCount = modCount; 5  6     public boolean hasNext() { 7         return cursor != size; 8     } 9 10     @SuppressWarnings("unchecked")11     public E next() {12         checkForComodification();13         int i = cursor;14         if (i >= size)15             throw new NoSuchElementException();16         Object[] elementData = ArrayList.this.elementData;17         if (i >= elementData.length)18             throw new ConcurrentModificationException();19         cursor = i + 1;20         return (E) elementData[lastRet = i];21     }22 23     public void remove() {24         if (lastRet < 0)25             throw new IllegalStateException();26         checkForComodification();27 28         try {29             ArrayList.this.remove(lastRet);30             cursor = lastRet;31             lastRet = -1;32             expectedModCount = modCount;33         } catch (IndexOutOfBoundsException ex) {34             throw new ConcurrentModificationException();35         }36     }37 38     final void checkForComodification() {39         if (modCount != expectedModCount)40             throw new ConcurrentModificationException();41     }42 }

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

原來Itr它是一個私人的內部類,實現Iterator介面。

我們來一行一行讀。在第3行中有一個modCount變數。跟蹤這個變數,發現這個變數有點意思:

protected transient int modCount = 0;

發現有一個“transient”關鍵字,查閱資料發現這個關鍵字的意思是:表示一個域不是該對象序列化的一部分。意思是在對象被序列化時不包括這個變數,至於為什麼要這麼做呢,我們可以留下一個疑問。(JDk源碼注釋中是這麼說的:The modCount value that the iterator believes that the backing List should have. If this expectation is violated, the iterator has detected concurrent modification.英語太次只能讀懂最後一句:如果這個期望是可見度的,那麼這個迭代器會檢測到有一個並發的修改。猜測是和並發多線程相關。)

hasnext的實現較為簡單:

1 public boolean hasNext() {2     return cursor != size;  //下一個元素的索引是否等於ArrayList的大小3 }

next的實現:

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

public E next() {    checkForComodification();  //檢查是否並發修改    int i = cursor;    if (i >= size)        throw new NoSuchElementException();  //索引大於ArrayList大小拋出異常    Object[] elementData = ArrayList.this.elementData;  //後面實際是在取ArrayList中的資料    if (i >= elementData.length)        throw new ConcurrentModificationException();    cursor = i + 1;    return (E) elementData[lastRet = i];}

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

在next方法中我們看到有一個checkForCommodification方法:

final void checkForComodification() {    if (modCount != expectedModCount)        throw new ConcurrentModificationException();}

看來這個modCount變數確實是和並發相關,如果expectedModCount和modCount這兩個值不同,則拋出當前正在並發修改的異常。

最後我們來看remove方法的實現:

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

public void remove() {    if (lastRet < 0)  //這個地方格外注意,不能在未調用next時直接調用remove方法,必須在remove調用前調用next方法,將通過cursor索引值將其值賦給lastRet        throw new IllegalStateException();    checkForComodification();    try {        ArrayList.this.remove(lastRet);        cursor = lastRet;        lastRet = -1;        expectedModCount = modCount;    } catch (IndexOutOfBoundsException ex) {        throw new ConcurrentModificationException();    }}

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

在remove方法中我們要格外注意,在第一句是檢測lastRet是否小於0,我們初始化了lastRet變數-1的值,這意味著,如果我們如果建立完Iterator執行個體後直接調用remove方法會拋出一個IllegalStateException異常,那怎麼才能正確調用呢?那就是在調用remove方法前先調用next方法,此時lastReturn通過cursor索引被賦值,這個時候才能正確使用remove方法。同時它也會調用checkForCommodification方法做並發修改檢測。其實我們可以看到JDK源碼之所以寫到好,是因為它每個方法都做了很多的檢測,以確保在盡量多的情境下準確無誤地運行。今天關於Java的迭代器就通過JDK源碼簡單介紹,通過對源碼的閱讀能夠加深我們的理解,這還只是簡單的閱讀,並沒有做很深的理解。最後,我們以為一個Iterator的例子結尾。

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />

 1 package day_29_iterator; 2  3 import java.util.ArrayList; 4 import java.util.Iterator; 5 import java.util.List; 6  7 /** 8  * @author turbo 9  *10  * 2016年9月29日11  */12 public class Main {13 14     /**15      * @param args16      */17     public static void main(String[] args) {18         List list = new ArrayList();19         list.add(1);20         list.add(2);21         Iterator iterator = list.iterator();22         while (iterator.hasNext()){23             System.out.println(iterator.next());24         }25     }26 27 }

650) this.width=650;" src="/img/fz.gif" alt="複製代碼" style="margin:0px;padding:0px;border:none;" />


Java迭代器Iterator

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.