您的位置:首页 > 编程语言 > Java开发

使用Iterator 或for-each注意:java.util.ConcurrentModificationException

2010-05-01 00:35 627 查看

使用Iterator 或for-each注意:java.util.ConcurrentModificationException

Posted on 2010-03-02 12:22 Fingki.li 阅读(1360) 评论(1) 编辑 收藏 所属分类: About development


在使用Iterator处理Collection时,注意java.util.ConcurrentModificationException。
1.如果你仅仅是对collection进行遍历查询,那么不必担心什么。
2.但如果你在遍历过程中要对collection进行删除,那么你就要注意了。
For example:
private void testDel() {
List<String> list = new ArrayList<String>();

for (int i = 0; i < 10; i++) {

String str = "td" + i;

list.add(str);

}



for (Iterator it = list.iterator(); it.hasNext();) {

String str = (String) it.next();

if (str.equals("td5")) {

// list.remove(str); // 删除方法一

it.remove(); // 删除方法二

}

}

}

上面的代码运行没有问题,但如果你用“方法一”替代“方法二”,则会出现java.util.ConcurrentModificationException。
(用for-each遍历也会出个类似问题)
具体原因是可以看一下先看看List中的remove方法源码:

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的值

int numMoved = size - index - 1;

if (numMoved > 0)

System.arraycopy(elementData, index + 1, elementData, index,

numMoved);

elementData[--size] = null; // Let gc do its work

}

接着看。删除后得到下一个元素的代码,it.next(): it为AbstractList的内部类Iterator的一个实例。

public E next() {

checkForComodification();

try {

E next = get(cursor);

lastRet = cursor++;

return next;

} catch (IndexOutOfBoundsException e) {

checkForComodification();

throw new NoSuchElementException();

}

}



final void checkForComodification() { //注意这个方法

if (modCount != expectedModCount) //检查这两个值是否相同

throw new ConcurrentModificationException();

}

最后看Iterator的remove()方法的源代码:

public void remove() {

if (lastRet == -1)

throw new IllegalStateException();

checkForComodification();

try {

AbstractList.this.remove(lastRet);

if (lastRet < cursor)

cursor--;

lastRet = -1;

expectedModCount = modCount; // 设置expectedModCount

} catch (IndexOutOfBoundsException e) {

throw new ConcurrentModificationException();

}

}



final void checkForComodification() {

if (modCount != expectedModCount)

throw new ConcurrentModificationException();

}

这下就明白了,list的remove方法只修改了modCount值,而iterator的remove能同步modCount和expectedModCount.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐