集合迭代器原理刨解JDK1.8(2)

1.ArrayList中的迭代器
ArrayList實現了迭代器接口,返回一個Itr內部類對象

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

2.Itr實現了Iterator接口,有個三個實例成員變量
首先理清楚foreach或獲取Iterator跌代器對象,就用expectedModCount變量,
記錄當前集合modCount變量的次數expectedModCount = modCount。
如果在遍歷過程中,發現modCount != expectedModCount不相等,
說明用集合add或remove等方法,修改了當前集合元素,就報併發修改異常。

1.下一個要返回的元素位置

2.最後一個返回的索引位置,如果沒有,返回-1

3.expectedModCount表示期望修改的次數,初始化外部類當前的修改次數modCount,
成員內部類可以直接訪問外部類的實例變量,每次外部類modCount發生變化會增加,
迭代的時候,會比較expectedModCount和modCount是否相同,不相同會報異常。

4.checkForComodification()檢查是否發生變化,沒有發生變化。下面就更新cursorlastRet以及expectedModCount的值相同,返回元素對象

5.調用ArrayList的remove方法之前,同時更新上面第4點的值,所以能正確刪除。調用remove刪除方法之前必須next,不然會報錯

List<Integer> list = new ArrayList<Integer>();
        list.add(22);
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
        		//iterator.next();
                iterator.remove();

Exception in thread “main” java.lang.IllegalStateException

protected transient int modCount = 0;

 private class Itr implements Iterator<E> {
        int cursor;       //1
        int lastRet = -1; //2
        int expectedModCount = modCount;//3

        public boolean hasNext() {
            return cursor != size;
        }

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification(); //4
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = i];
        }
	
        public void remove() { //5
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

檢查方法

final void checkForComodification() {
  		//modCount變量修改次數和期望修改的次數不一樣就報異常
            if (modCount != expectedModCount) 
                throw new ConcurrentModificationException();
        }

總結
迭代器的好處在容器裏面更通用,提供了遍歷和數據分離的模式,不互相影響。這個Iterator接口對象的作用是遍歷,設計成內部類的好處,可以方便直接訪問自己集合內部元素。使用起來只要list.iterator()使用接口的引用就可以。
好比飛機汽車火車上的空姐 只爲當前的飛機裏元素服務,別的飛機有別的空姐,反應出每個集合的迭代器只爲當前的集合服務.

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