foreach循环的时候remove的问题

来源:互联网 发布:十字绣软件 编辑:程序博客网 时间:2024/04/29 19:28

在foreach循环ArrayList期间remove了其中一个元素,然后就报错了:

Exception in thread "main" java.util.ConcurrentModificationException

用Iterator循环的时候会出现类似的问题。

如果真的要在循环期间remove元素,需要使用for(int i=0;i<list.size();i++)的这种形式。

问题的来源:

问题的来源在于ArrayList的父类AbstractList,是个抽象类,这个类在使用Iterator时使用了一种叫做fail-fast的错误机制,当Iterator在访问ArrayList期间,如果这个ArrayList被改变了,则会抛出ConcurrentModificationException异常。

AbstractList的部分代码是这样的:

package java.util;public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {    ...    // AbstractList中唯一的属性    // 用来记录List修改的次数:每修改一次(添加/删除等操作),将modCount+1    protected transient int modCount = 0;    // 返回List对应迭代器。实际上,是返回Itr对象。    public Iterator<E> iterator() {        return new Itr();    }    // Itr是Iterator(迭代器)的实现类    private class Itr implements Iterator<E> {        int cursor = 0;        int lastRet = -1;        // 修改数的记录值。        // 每次新建Itr()对象时,都会保存新建该对象时对应的modCount;        // 以后每次遍历List中的元素的时候,都会比较expectedModCount和modCount是否相等;        // 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。        int expectedModCount = modCount;        public boolean hasNext() {            return cursor != size();        }        public E next() {            // 获取下一个元素之前,都会判断“新建Itr对象时保存的modCount”和“当前的modCount”是否相等;            // 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。            checkForComodification();            try {                E next = get(cursor);                lastRet = cursor++;                return next;            } catch (IndexOutOfBoundsException e) {                checkForComodification();                throw new NoSuchElementException();            }        }        public void remove() {            if (lastRet == -1)                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();        }    }    ...}
也就是说,每次修改List时,会改变modCount的值,而Iterator每次调用next()方法时,会判断这个List的modCount和一开始的值是不是一样,如果不一样,就直接抛异常。


0 0