【JDK1.8源碼剖析】外部迭代器Iterator接口

Iterator源碼剖析

(一)簡介

Iterabtor是從jdk1.2就存在的接口,稱爲外部迭代器。支持對容器中的元素進行遍歷和移除,還支持流式遍歷

外部迭代器的特點是:可拔插。其迭代行爲可以掛載到待比較對象的外部, 此外,外部迭代器往往用來支撐內部迭代器的實現。

注意區別於內部迭代器Iterable和枚舉器Enumeration

外部迭代器的設計背後體現着迭代器設計模式的思想

(二)源碼分析

該接口就只有四種方法
在這裏插入圖片描述

    // 是否存在未遍歷元素
    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());
        }
    }

Consumer爲一個函數式接口,擇取從這裏實現。Lambda表達式參考【Java 8 in Action】Lambda表達式

我們看一下外部迭代器是如何實現自己的作用的。

我們切到AbstractList抽象類。很容易發現存在Itr類實現了外部迭代器的接口

// 獲取類的迭代器
public Iterator<E> iterator() {
        return new Itr();
}
// 修改的次數--集合的增刪改查;都能引起modCount數值加1的操作
protected transient int modCount = 0;

private class Itr implements Iterator<E> {
        
        // 下一個元素的索引
        int cursor = 0;

        // 當前元素的索引,該索引的元素被刪除了,則置爲-1.
        int lastRet = -1;

		// 預期修改的次數
        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();
            }
        }

		// 這個方法體現的是Fail-Fast機制。
		// expectedModCount預期修改的次數,modCount就是實際修改的次數;
		// 在迭代器中,首先定義了一個expectedModCount=modCount默認值是0;這樣通過上面的checkForComodification()方法就可以判斷list集合在迭代過程中是否被其他線程修改過,這裏的修改就是集合的增刪改查;因爲這些操作都能引起modCount數值加1的操作,這樣就使得迭代失敗了。
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

ArrayList繼承了AbstractList抽象類。知曉源碼之後,我們再使用迭代器的API,一切都是那麼自然。

    public static void main(String[] args) {
        
        ArrayList<String>  name= new ArrayList<>();
        name.add("zhangsan");
        name.add("lisi");
        name.add("wangwu");
        name.add("zhaoliu");
        Iterator<String> it=name.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }

在這裏插入圖片描述

還有,checkForComodification方法,體現的是Fail-Fast機制(面試會問)。也說明了爲什麼外部迭代器遍歷的時候,如果對集合進行操作,會拋出ConcurrentModificationException異常了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章