[Java]迭代器(Iterator)

迭代器(Iterator)是一個對象,它的工作是遍歷並選擇序列中的對象,它提供了一種訪問一個容器(container)對象中的各個元素,而又不必暴露該對象內部細節的方法。通過迭代器,開發人員不需要了解容器底層的結構,就可以實現對容器的遍歷。由於創建迭代器的代價小,因此迭代器通常被稱爲輕量級的容器。

迭代器的使用主要有以下三個方面的注意事項:
1)使用容器的iterator()方法返回一個Iterator,然後通過Iterator的next()方法返回第一個元素。
2)使用Iterator()的hasNext()方法判斷容器中是否還有元素,如果有,可以使用next()方法獲取下一個元素。
3)可以通過remove()方法刪除迭代器返回的元素。

Iterator支持派生的兄弟成員。ListIterator只存在於List中,支持在迭代期間向List中添加或刪除元素,並且可以在List中雙向滾動。

Iterator的使用方法如下例所示:

package com.js;
/**
 * Iterator使用Demo
 */
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class Test {
    public void main(String[] args){
        List<String> ll = new LinkedList<String>();
        ll.add("first");
        ll.add("second");
        ll.add("third");
        ll.add("fourth");
        for(Iterator<String> iterator = ll.iterator();iterator.hasNext();){
            String string = (String)iterator.next();
            System.out.println(string);
        }
    }
}

運行結果爲:

first
second
third
fourth

使用iterator()方法時經常會遇到ConcurrentModificationException異常,這通常是由於在使用Iteraor遍歷容器的同時又對容器做增加或刪除操作所導致的,或者由於多線程操作導致,當一個線程使用迭代器遍歷容器的同時,另外一個線程對這個容器進行增加或刪除操作。下列主要介紹單線程拋出ConcurrentModificationException的情況:

package com.js;
/**
 * Iterator使用Demo
 */
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class Test {
    public void main(String[] args){
        List<String> ll = new LinkedList<String>();
        ll.add("first");
        ll.add("second");
        ll.add("third");
        ll.add("fourth");
        for(Iterator<String> iterator = ll.iterator();iterator.hasNext();){
            String string = (String)iterator.next();
            System.out.println(string);
            if(string.equals("second"))
                ll.add("fifth");// 拋出:ConcurrentModificationException
        }
    }
}

運行結果爲:


first
second
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.next(Unknown Source)
at com.js.Test.main(Test.java:17)

拋出上述異常的主要原因是:
在使用Iterator的時候,迭代器會新建一個線程,把原來的線程中的對象重新拷貝一份,在進行刪除,修改等操作時,原來的線程只負責迭代,而Iterator負責迭代和刪除操作,Iterator每次迭代都會檢查迭代器裏的對象和原線程中的對象個數是否一致,不一致則拋出:ConcurrentModificationException。
解決辦法 :
不能使用集合中的remove方法,使用Iterrator中的remove方法。

Iterator中的remove

default void remove() 
從基礎集合中移除這個迭代器返回的最後一個元素(可選操作)。兩個線程中都刪除,保證線程的同步。

使用迭代器對象調用其中的remove方法,以保證線程同步。

正確使用方法:

 for (Iterator<String> iterator : ll.iterator() ) {
           String string = (String)iterator.next();
            if(string.equals("second"))
                iterator.remove();
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章