集合迭代器原理刨解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()使用接口的引用就可以。
好比飞机汽车火车上的空姐 只为当前的飞机里元素服务,别的飞机有别的空姐,反应出每个集合的迭代器只为当前的集合服务.

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