在iterator过程中使用list.remove,报错Exception in thread "main" java.util.ConcurrentModificationException
package collect; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class myiterator { public static void main(String[] args) { List<String> list =new ArrayList<String>(); list.add("China"); list.add("hello"); list.add("world"); Iterator<String> it =list.iterator(); System.out.println(list.size()); int i = 0,j=0; while (it.hasNext()) { it.next(); i++; list.remove("hello"); System.out.println("运行第"+i+"次"); } } }
结果
3 运行第1次 Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at collect.myiterator.main(myiterator.java:18)
同时修改异常,就是在iterator运行过程中,因为list修改而报错的异常
源代码的角度来说:当arrarlist调用iterator的时候,返回一个Itr的引用
public Iterator<E> iterator() { return new Itr(null); }
在arraylist中找到Itr的类
private class Itr implements Iterator<E> { int cursor; int lastRet = -1; int expectedModCount = modCount; private Itr() {} public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; if (i >= size) { throw new NoSuchElementException(); } Object[] arrayOfObject = elementData; if (i >= arrayOfObject.length) { throw new ConcurrentModificationException(); } cursor = (i + 1); return (E)arrayOfObject[(lastRet = i)]; } public void remove() { if (lastRet < 0) { throw new IllegalStateException(); } checkForComodification(); try { remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = modCount; } catch (IndexOutOfBoundsException localIndexOutOfBoundsException) { throw new ConcurrentModificationException(); } }
checkForComodification();这个方法
final void checkForComodification() { if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }
判断一下modCount != expectedModCount是否相等,不等的话抛出ConcurrentModificationException();
modCount属于 AbstractList<E>类的protected transient int modCount = 0;初始为0
expectedModCount属于ArrayList<E>下面的Itr类的
int expectedModCount = modCount;
当arraylist调用remove方法时,调用的是arraylist下面的remove跟fastRemove对应方法
public E remove(int paramInt) { rangeCheck(paramInt); modCount += 1; Object localObject = elementData(paramInt); int i = size - paramInt - 1; if (i > 0) { System.arraycopy(elementData, paramInt + 1, elementData, paramInt, i); } elementData[(--size)] = null; return (E)localObject; } public boolean remove(Object paramObject) { int i; if (paramObject == null) { for (i = 0; i < size; i++) { if (elementData[i] == null) { fastRemove(i); return true; } } } else { for (i = 0; i < size; i++) { if (paramObject.equals(elementData[i])) { fastRemove(i); return true; } } } return false; } private void fastRemove(int paramInt) { modCount += 1; int i = size - paramInt - 1; if (i > 0) { System.arraycopy(elementData, paramInt + 1, elementData, paramInt, i); } elementData[(--size)] = null; }
当调用remove(int paramInt)时,modCount+= 1;会+1改变modCount 的值
当调用remove(Object paramObject) ,会调用fastRemove(int paramInt) 接着modCount += 1;会+1改变modCount 的值
总之,ArrayList<E>下面的remove方法会改变modCount的值,remove一次,使其+1一次
总结:现在从头看一下,当Iterator<String> it =list.iterator();时,创建一个Itr引用,
并且内部int expectedModCount = modCount;,来自于AbstractList<E> 的protected transient int modCount = 0;
现在expectedModCount跟modCount都等于0,在执行完arraylist的remove方法后modCount值+1,
然后程序执行iterator.next(); 其中checkForComodification()判断expectedModCount跟modCount值不等,然后thrownew ConcurrentModificationException();
同样在iterator里面进行list.add也会导致modCount值+1 报错
add方法每次都会ensureCapacityInternal确保容量够用
public boolean add(E paramE) { ensureCapacityInternal(size + 1); elementData[(size++)] = paramE; return true; } public void add(int paramInt, E paramE) { rangeCheckForAdd(paramInt); ensureCapacityInternal(size + 1); System.arraycopy(elementData, paramInt, elementData, paramInt + 1, size - paramInt); elementData[paramInt] = paramE; size += 1; }
然后这里面就会执行modCount += 1;
private void ensureCapacityInternal(int paramInt) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { paramInt = Math.max(10, paramInt); } ensureExplicitCapacity(paramInt); } private void ensureExplicitCapacity(int paramInt) { modCount += 1; if (paramInt - elementData.length > 0) { grow(paramInt); } }
这里面是判断是否存在对象,
假如list里面什么都没有因为iterator.hasNext()都进不去,在iterator里面可以写list.add方法,不过东西加入到list的里面,输出结果还是为空,
如果list存在值这时进入iterator遍历,先判断是否存在,不过hasNext()判断过了,肯定存在
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { paramInt = Math.max(10, paramInt); }
所以一定执行ensureExplicitCapacity,modCount+= 1;,导致iterator里面list.add失败
相关内容: