工作中碰到个concurrentmodificationexception。代码如下:
list list = ...;for(iterator iter = list.iterator(); iter.hasnext();) { object obj = iter.next(); ... if(***) { list.remove(obj); }}
<span style="color: #0000ff;"><br></span>在执行了remove方法之后,再去执行循环,iter.next()的时候,报java.util.concurrentmodificationexception(当然,如果remove的是最后一条,就不会再去执行next()操作了)<br><br>下面来看一下源码
public interface iterator<e> { boolean hasnext(); e next(); void remove();}public interface collection<e> extends iterable<e> { ... iterator<e> iterator(); boolean add(e o); boolean remove(object o); ...}
<br>这里有两个remove方法<br><br>接下来来看看abstractlist
public abstract class abstractlist<e> extends abstractcollection<e> implements list<e> { //abstractcollection和list都继承了collection protected transient int modcount = 0; private class itr implements iterator<e> { //内部类itr int cursor = 0; int lastret = -1; int expectedmodcount = modcount; public boolean hasnext() { return cursor != size(); } public e next() { 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); //执行remove对象的操作 if (lastret < cursor) cursor--; lastret = -1; expectedmodcount = modcount; //重新设置了expectedmodcount的值,避免了concurrentmodificationexception的产生 } catch(indexoutofboundsexception e) { throw new concurrentmodificationexception(); } } final void checkforcomodification() { if (modcount != expectedmodcount) //当expectedmodcount和modcount不相等时,就抛出concurrentmodificationexception throw new concurrentmodificationexception(); } } }remove(object o)在arraylist中实现如下: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++; //只增加了modcount ....}
<span style="color: #0000ff;"><br><span style="color: #339966;"><br><strong style="color: #800000;">所以,产生concurrentmodificationexception的原因就是:<br>执行remove(object o)方法之后,modcount和expectedmodcount不相等了。然后当代码执行到next()方法时,判断了checkforcomodification(),发现两个数值不等,就抛出了该exception。<br>要避免这个exception,就应该使用remove()方法。</strong></span>[b]<br>[/b]</span>这里我们就不看add(object o)方法了,也是同样的原因,但没有对应的add()方法。一般嘛,就另建一个list了<br><br><br>下面是网上的其他解释,更能从本质上解释原因:<br>iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 iterator 会马上抛出 java.util.concurrentmodificationexception 异常。<br>所以 iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 iterator 本身的方法 remove() 来删除对象, iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。