java迭代器

与java迭代器相关的类的继承关系

java迭代器继承体系.png

ArrayList中的迭代器

其实获取ArrayList的迭代器是一个Iterator的实现-Itr,定义如下。

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
{
   public Iterator iterator() {
        return new Itr();
    }

}

ArrayList中定义了一个内部类Itr,实现了ListIterator接口。

private class Itr implements Iterator {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

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

        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            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() {
            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() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }

迭代的时候操作原始集合

public static void main(String[] args) {
        Collection list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");

        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            if (iterator.next() == "a"){
                list.remove("a");
            }
        }
    }

上述代码的执行结果

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
    at java.util.ArrayList$Itr.next(ArrayList.java:859)
    at org.learnspring.service.v2.PetStoreService.main(PetStoreService.java:55)

报错的原因分析如下:
迭代器的next方法,每次都会判断两个变量的值是否相等,不相等就会报ConcurrentModificationException。其中的两个变量分别是定义在Itr中的expectedModCount和定义在ArrayList中的modCount。而判断的方法是定义在ItrcheckForComodification方法。

如何在迭代器迭代的时候操作原始集合

我们可以使用迭代器自己的remove方法来删除集合中被扫描到的元素。

public static void main(String[] args) {
        Collection list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");

        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            if (iterator.next() == "a"){
                iterator.remove();
            }
        }
        System.out.println(list);
    }

执行结果

[b, c, d, e]

我们分析迭代器中的remove方法,发现它内部是调用ArrayListremove方法来移除元素的,ArrayList.this.remove(lastRet);

那么,为什么这样就不会报错呢?
因为,每次remove之后都会将迭代器的指针向前推移一位,保证了迭代器能够扫描到集合中所有的元素。
同时确保两个变量的值相等,通过赋值的操作来保证。

你可能感兴趣的:(java迭代器)