使用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.
相关文章推荐
- 使用Iterator 或for-each注意:java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 解决办法(使用迭代器时出现异常)
- java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListIterator.next(ArrayList.
- 在使用set/map时,一个可爱的小bug:java.util.ConcurrentModificationException
- Iterator遍历时报错 java.util.ConcurrentModificationException
- Iterator 迭代 警惕 java.util.ConcurrentModificationException异常
- 使用迭代器遍历集合时,当集合中的数据发生变化是会抛出java.util.ConcurrentModificationException异常
- java使用Iterator迭代出现"java.uitl.ConcurrentModificationException"错误原因及解决方法概述
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException原因
- java.util.ConcurrentModificationException 解决办法
- java.util.ConcurrentModificationException异常处理
- 关于 Java.util.ConcurrentModificationException 的讨论和解决方法
- Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException 解决办法
- 关于dubbo使用过程中抛出【java.util.concurrent.RejectedExecutionException: Thread pool is EXHAUSTED!】的思考
- Java Iterator ListIterator 迭代器 以及 并发修改异常 ConcurrentModificationException
- java.util.ConcurrentModificationException
- java.util.ConcurrentModificationException异常最简单的解决办法
- LinkedList - java.util.ConcurrentModificationException