天天看點

Java Review (二十五、集合----- Iterator接口)

Iterator接口 也是 Java 集合架構的成員 , 但它與 Collection 系列 、 Map 系列 的集合不 一樣 : Collection系列集合、 Map 系列集合主要用于盛裝其他對象,而 Iterator 則主要用于周遊(即疊代通路) Collection集合中的元素, Iterator 對象也被稱為疊代器 。

Iterator 接口隐藏了各種 Collection實作類的底層細節,向應用程式提供了周遊 Collection 集合元素的統一程式設計接口 。

Iterator 接口裡定義了如下 4 個方法 :

  • boolean hasNext(): 如果被疊代的集合元素還沒有被周遊完 ,則傳回 true 。
  • Object next(): 傳回集合裡的下一個元素 。
  • void remove(): 删除集合裡上一次 next 方法傳回的元素 。
  • void forEachRemaining(Consumer action) ,這是 Java 8 為Iterator 新增的預設方法,該方法可使用Lambda 表達式來周遊集合元素 。

下面程式示範了通過 Iterator 接口來周遊集合元素 :

public class IteratorTest
{
    public static void main(String[] args)
    {
        // 建立集合、添加元素的代碼與前一個程式相同
        Collection books = new HashSet();
        books.add("輕量級Java EE企業應用實戰");
        books.add("瘋狂Java講義");
        books.add("瘋狂Android講義");
        // 擷取books集合對應的疊代器
        Iterator it = books.iterator();
        while(it.hasNext())
        {
            // it.next()方法傳回的資料類型是Object類型,是以需要強制類型轉換
            String book = (String)it.next();
            System.out.println(book);
            if (book.equals("瘋狂Java講義"))
            {
                // 從集合中删除上一次next方法傳回的元素
                it.remove();
            }
            // 對book變量指派,不會改變集合元素本身
            book = "測試字元串";   //①
        }
        System.out.println(books);
    }
}      
Iterator 僅用于周遊集合 , Iterator 本身并不提供盛裝對象的能力 。

當使用 Iterator 疊代通路 Collection 集合元素時 , Collection 集合裡的元素不能被改變,隻有通過Iterator 的 remove()方法删除上 一 次 next()方法傳回的集合元素才可以;否則将會引發 java .util.ConcurrentModificationException 異常 。 下面程式示範了這一 點 :

public class IteratorErrorTest
{
    public static void main(String[] args)
    {
        // 建立集合、添加元素的代碼與前一個程式相同
        Collection books = new HashSet();
        books.add("輕量級Java EE企業應用實戰");
        books.add("瘋狂Java講義");
        books.add("瘋狂Android講義");
        // 擷取books集合對應的疊代器
        Iterator it = books.iterator();
        while(it.hasNext())
        {
            String book = (String)it.next();
            System.out.println(book);
            if (book.equals("瘋狂Android講義"))
            {
                // 使用Iterator疊代過程中,不可修改集合元素,下面代碼引發異常
                books.remove(book);
            }
        }
    }
}      

Iterator 法代器采用的是快速失敗( fail-fast ) 機制, 一 旦在疊代過程中檢測到該集合己經被修改(通常是程式中的其他線程修改),程式立即引發 ConcurrentModificationException 異常,而不是顯示修改後的結果,這樣可以避免共享資源而引發的潛在問題。

Java 8 起為Iterator 新增了 一個 forEachRemaining(Consumer action)方法,該方法所需的 Consumer參數同樣也是函數式接口 。 當程式調用 Iterator 的 forEachRemaining(Consumer action)周遊集合元素時,程式會依次将集合元素傳給 Consumer的 accept(T t)方法(該接口中唯一的抽象方法) 。

如下程式示範了使用 Lambda 表達式來周遊集合元素:

public class IteratorEach
{
    public static void main(String[] args)
    {
        // 建立集合、添加元素的代碼與前一個程式相同
        Collection books = new HashSet();
        books.add("輕量級Java EE企業應用實戰");
        books.add("瘋狂Java講義");
        books.add("瘋狂Android講義");
        // 擷取books集合對應的疊代器
        Iterator it = books.iterator();
        // 使用Lambda表達式(目标類型是Comsumer)來周遊集合元素
        it.forEachRemaining(obj -> System.out.println("疊代集合元素:" + obj));
    }
}      

除了使用疊代器以外,使用 Java 5 提供的 foreach 循環疊代通路集合元素更加便捷 。

如下程式示範了使用 foreach 循環來疊代通路集合元素 :

public class ForeachTest
{
    public static void main(String[] args)
    {
        // 建立集合、添加元素的代碼與前一個程式相同
        Collection books = new HashSet();
        books.add(new String("輕量級Java EE企業應用實戰"));
        books.add(new String("瘋狂Java講義"));
        books.add(new String("瘋狂Android講義"));
        for (Object obj : books)
        {
            // 此處的book變量也不是集合元素本身
            String book = (String)obj;
            System.out.println(book);
            if (book.equals("瘋狂Android講義"))
            {
                // 下面代碼會引發ConcurrentModificationException異常
                books.remove(book);     //①
            }
        }
        System.out.println(books);
    }
}      
API: java.util.Iterator

參考:

【1】:《瘋狂Java講義》