JAvaのiteratorとcollectionインタフェースのソースコード

4819 ワード

iteratorインタフェースと特定のコンテナで実装されるiteratorオブジェクト(ArrayListを例に)
iterator:
public interface Iterator {
    boolean hasNext();    
    E next();
 
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
   
    default void forEachRemaining(Consumer super E> action) {
        Objects.requireNonNull(action);
        while (hasNext())
            action.accept(next());
    }
}
AbstractListの内部クラスItrは、以下に示すように、Iteratorインタフェースを実現する.
private class Itr implements Iterator {
        /**     
         * Index of element to be returned by subsequent call to next.
         */
        int cursor = 0;

        /**        。            -1
         * Index of element returned by most recent call to next or
         * previous.  Reset to -1 if this element is deleted by a call
         * to remove.
         */
        int lastRet = -1;

        /**       ,        
         * The modCount value that the iterator believes that the backing
         * List should have.  If this expectation is violated, the iterator
         * has detected concurrent modification.
         */
        int expectedModCount = modCount;
       /*           */
        public boolean hasNext() {
            return cursor != size();
        }
      /*    ,         */
        public E next() {
            checkForComodification();
            try {
                int i = cursor;
                E next = get(i);
                lastRet = i;
                cursor = i + 1;
                return next;
            } catch (IndexOutOfBoundsException e) {
                checkForComodification();
                throw new NoSuchElementException();
            }
        }
       /*    */
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }

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

ArrayListのiterator()メソッド:
 public Iterator iterator() {
        return new Itr();
    }

collectionソース:
/** 
 * Collection   collection     ; 
 * Collection   Iterable,    Collection       foreach  。 
 * @author WGS 
 * @param  
 */
public interface Collection extends Iterable {
    //          。(        Integer.MAX_VALUE,     Integer.MAX_VALUE) 
    int size();
    //         
    Boolean isEmpty();
    //          o(    e   null         ) 
    Boolean contains(Object o);
    //           (      ,         ) 
    Iterator iterator();
    //                ,      
    Object[] toArray();
    //                   
     T[] toArray(T[] a);
    //                 e; -false, -true( set,map          ,        ) 
    Boolean add(E e);
    //            
    Boolean remove(Object o);
    //                   
    Boolean containsAll(Collection> c);
    //                      
    Boolean addAll(Collection extends E> c);
    //            (          ) 
    Boolean removeAll(Collection> c);
    //             (             ) 
    Boolean retainAll(Collection> c);
    //     
    void clear();
    //            
    Boolean equals(Object o);
    //          
    int hashCode();
}

反復する前に反復器がlistを通過したからですitertor()が作成され、反復中にlistがコンテナサイズを変更する操作を行うとJavaは例外を与えます.この時点でIteratorオブジェクトはlistの変更をアクティブに同期できないため、Javaはスレッドが安全ではないと判断し、善意の注意を払う(C o n c u r e ntModificationException異常を投げ出す)
ソースコードを確認して、元のチェックと例外を投げ出すのがcheckForComodification()メソッドです.ArrayListではmodCountは現在のコレクションのバージョン番号であり、修正(追加、削除)するたびにコレクションに1が加算されます.expectedModCountは、現在の反復器のバージョン番号であり、反復器のインスタンス化時にmodCountに初期化されます.checkForComodification()メソッドでは、modCountの値とexpectedModCountの値が等しいかどうかを検証するため、ArrayListを呼び出す.add()またはArrayList.remove()の場合、modCountの状態のみが更新、反復器のexpectedModCountが同期していないため、Iteratorが再起動する.next()メソッド時に異常を放出します.でもなぜ?remove()は大丈夫ですか?ソースコードの32行目により、Iteratorのremove()でexpectedModCountの値が同期されていることが判明したので、次回next()を呼び出すと、異常が放出されないことを確認します.
このメカニズムを用いた主な目的は,Java集合の大部分の集合に高速失敗メカニズムが存在するArrayListにおける高速失敗メカニズム(fail-fast)を実現することである.
Fast Failureメカニズムによって生成される条件:複数のスレッドがCollectionを操作している間に、あるスレッドがIteratorを介してコレクションを巡回している間に、そのセットの内容が他のスレッドによって変更されると、ConcurrentModificationException例外が放出されます.
したがって,Iteratorを用いて集合を巡回する際に誤りがないことを保証するには,集合を巡回する過程で集合に構造的な修正が生じないことを保証しなければならない.