黑马程序员技术交流社区

标题: 迭代器ConcurrentModificationException异常出现 [打印本页]

作者: guyouzhong    时间: 2017-1-18 22:45
标题: 迭代器ConcurrentModificationException异常出现
迭代器遍历集合时同时使用集合自带的方式修改了集合.就会出现并发修改异常.
        如果使用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异常。

作者: guyouzhong    时间: 2017-1-18 22:46
大家赶紧来监督,提出问题,快快,孩子们
作者: Mbs2016    时间: 2017-1-30 07:11
没人啊。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2