A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

迭代器遍历集合时同时使用集合自带的方式修改了集合.就会出现并发修改异常.
        如果使用Literator迭代器,那么在迭代期间可以使用Remove()方法不会报错;在迭代不能使用集合的add、Remove等改变集合内部元素的方法。
查看底层源码:
[Java] 纯文本查看 复制代码
1.	list.listIterator().得到的是一个迭代器,查看源码:
public Iterator<E> iterator() {    return new Itr();   }
以上获得迭代器的代码
2.	下面看Itr这个类中写了什么:
private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return
    int lastRet = -1; // index of last element returned; -1 if no such
    int expectedModCount = modCount;
    public boolean hasNext() {       return cursor != size;    }
    public E next() {
        checkForComodification();
        int i = cursor;
        ...
    }
    public void remove() {        checkForComodification();    ...    }
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}
迭代器在next和remove的时候都会调用checkForComodification()检查modCount和expectedModCount的值是否相等。这里的expectedModCount是一个预期的值.而modCount是从AbstractList类中继承过来的,那么他是做什么用呢?
3.	接下来我们查看ArrayList集合的源码
        public boolean add(E e) {
        ensureCapacityInternal(size + 1);  //*** Increments modCount!!***//
        elementData[size++] = e;
        return true;
}
注意这里有一句备注Increments modCount!!
4. 接着看ensureCapacityInternal()方法,
    private void ensureCapacityInternal(int minCapacity) {
        ……………
        ensureExplicitCapacity(minCapacity);
    }
private void ensureExplicitCapacity(int minCapacity) {   modCount++;  …… ;}

同样查看remove()方法调用时候也会将modCount++。
其实这里的modCount表示的是对集合的修改次数. expectedModCount是在获得迭代器的时候由modCount赋值给它,也就是说Itr类中checkForComodification方法将expectedModCount和modCount比较后,如果发现,在迭代器开启后还使用集合中的add、remove方法修改了集合,那么迭代就会抛出ConcurrentModificationException异常。

2 个回复

倒序浏览
大家赶紧来监督,提出问题,快快,孩子们
回复 使用道具 举报
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马