ConcurrentModificationException

来源:互联网 发布:乐高机器人编程书 编辑:程序博客网 时间:2024/05/16 14:19

问题代码:

public static void main(String[] args) {    List<String> list = new ArrayList<>();    list.add("a");    list.add("b");    list.add("c");    list.add("d");    Iterator<String> iterator = list.iterator();    while (iterator.hasNext()) {        if (iterator.next().equals("c")) {            // list.remove("c");// 报错:ConcurrentModificationException            iterator.remove();// 可以运行        }    }}

ArrayList的remove()源码:

/** * 按下标删除 */public E remove(int index) {    rangeCheck(index);    modCount++;// 修改次数加1!!!    E oldValue = elementData(index);    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    elementData[--size] = null; // clear to let GC do its work    return oldValue;}
/** * 按元素删除 */public boolean remove(Object o) {    if (o == null) {        for (int index = 0; index < size; index++)            if (elementData[index] == null) {                fastRemove(index);                return true;            }    } else {        for (int index = 0; index < size; index++)            if (o.equals(elementData[index])) {                fastRemove(index);                return true;            }    }    return false;}private void fastRemove(int index) {    modCount++;// 修改次数加1!!!    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    elementData[--size] = null; // clear to let GC do its work}

ArrayList的Iterator源码:

public Iterator<E> iterator() {    return new 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;    }    @SuppressWarnings("unchecked")    public E next() {        checkForComodification();// 检查modCount和expectedModCount是否相等        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();// iterator的remove每次都会比较modCount和expectedModCount,若不等,则抛异常        try {            ArrayList.this.remove(lastRet);// 执行ArrayList的remove            cursor = lastRet;            lastRet = -1;            expectedModCount = modCount;// 同步modCount和expectedModCount,故iterator的remove不会抛异常        } catch (IndexOutOfBoundsException ex) {            throw new ConcurrentModificationException();        }    }    @Override    @SuppressWarnings("unchecked")    public void forEachRemaining(Consumer<? super E> consumer) {        Objects.requireNonNull(consumer);        final int size = ArrayList.this.size;        int i = cursor;        if (i >= size) {            return;        }        final Object[] elementData = ArrayList.this.elementData;        if (i >= elementData.length) {            throw new ConcurrentModificationException();        }        while (i != size && modCount == expectedModCount) {            consumer.accept((E) elementData[i++]);        }        // update once at end of iteration to reduce heap write traffic        cursor = i;        lastRet = i - 1;        checkForComodification();    }    final void checkForComodification() {        if (modCount != expectedModCount)            throw new ConcurrentModificationException();    }}

由源码可以看出:
ArrayList的remove修改modCount,但未同步Iterator的expectedModCount,所以执行iterator.next()的checkForComodification()时,抛出异常;而Iterator的remove,其实也是执行ArrayList的remove,但是每次都会同步expectedModCount,所以不会抛出异常。

原创粉丝点击