foreach循环的时候remove的问题
2016-10-31 11:18
302 查看
在foreach循环ArrayList期间remove了其中一个元素,然后就报错了:
Exception in thread "main" java.util.ConcurrentModificationException
用Iterator循环的时候会出现类似的问题。
如果真的要在循环期间remove元素,需要使用for(int i=0;i<list.size();i++)的这种形式。
问题的来源:
问题的来源在于ArrayList的父类AbstractList,是个抽象类,这个类在使用Iterator时使用了一种叫做fail-fast的错误机制,当Iterator在访问ArrayList期间,如果这个ArrayList被改变了,则会抛出ConcurrentModificationException异常。
AbstractList的部分代码是这样的:
package java.util;
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
...
// AbstractList中唯一的属性
// 用来记录List修改的次数:每修改一次(添加/删除等操作),将modCount+1
protected transient int modCount = 0;
// 返回List对应迭代器。实际上,是返回Itr对象。
public Iterator<E> iterator() {
return new Itr();
}
// Itr是Iterator(迭代器)的实现类
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
// 修改数的记录值。
// 每次新建Itr()对象时,都会保存新建该对象时对应的modCount;
// 以后每次遍历List中的元素的时候,都会比较expectedModCount和modCount是否相等;
// 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
// 获取下一个元素之前,都会判断“新建Itr对象时保存的modCount”和“当前的modCount”是否相等;
// 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
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);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
...
}也就是说,每次修改List时,会改变modCount的值,而Iterator每次调用next()方法时,会判断这个List的modCount和一开始的值是不是一样,如果不一样,就直接抛异常。
Exception in thread "main" java.util.ConcurrentModificationException
用Iterator循环的时候会出现类似的问题。
如果真的要在循环期间remove元素,需要使用for(int i=0;i<list.size();i++)的这种形式。
问题的来源:
问题的来源在于ArrayList的父类AbstractList,是个抽象类,这个类在使用Iterator时使用了一种叫做fail-fast的错误机制,当Iterator在访问ArrayList期间,如果这个ArrayList被改变了,则会抛出ConcurrentModificationException异常。
AbstractList的部分代码是这样的:
package java.util;
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
...
// AbstractList中唯一的属性
// 用来记录List修改的次数:每修改一次(添加/删除等操作),将modCount+1
protected transient int modCount = 0;
// 返回List对应迭代器。实际上,是返回Itr对象。
public Iterator<E> iterator() {
return new Itr();
}
// Itr是Iterator(迭代器)的实现类
private class Itr implements Iterator<E> {
int cursor = 0;
int lastRet = -1;
// 修改数的记录值。
// 每次新建Itr()对象时,都会保存新建该对象时对应的modCount;
// 以后每次遍历List中的元素的时候,都会比较expectedModCount和modCount是否相等;
// 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size();
}
public E next() {
// 获取下一个元素之前,都会判断“新建Itr对象时保存的modCount”和“当前的modCount”是否相等;
// 若不相等,则抛出ConcurrentModificationException异常,产生fail-fast事件。
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);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
...
}也就是说,每次修改List时,会改变modCount的值,而Iterator每次调用next()方法时,会判断这个List的modCount和一开始的值是不是一样,如果不一样,就直接抛异常。
相关文章推荐
- 集合已修改;枚举操作可能无法执行。使用foreach 循环删除DataRow的时候的问题! 该死的AcceptChanges() Row.elete() Remove(Row)使用不同。
- 使用foreach 循环删除DataRow的时候的问题
- [转]使用foreach 循环删除DataRow的时候的问题
- PHP中foreach循环传值问题
- java.util.ArrayList在foreach循环遍历时删除元素的问题
- PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么?
- Java方法中有循环的时候返回值问题
- mvc 不是成对标签出现在foreach循环里头问题
- smarty 中foreach中iteration变量值就是当前循环次数,在显示序号递增时候用到
- 关于foreach循环中遇到的问题小结
- 利用循环removeChild删除节点只删除一半问题
- 在做动态添加删除行的时候,使用jquery遇到的问题:$("#participantList tr").eq(i).remove();
- foreach中使用remove问题
- 不要在foreach 循环里进行集合元素的 remove/add 操作
- Maven项目如果涉及多个模块的话,设计的时候就要考虑模块循环依赖的问题
- 异步方法中map、forEach和for循环中带来的异步执行问题
- python list循环remove操作的神奇问题 推荐
- Java foreach循环, Iterator 迭代和remove方法之间的冲突
- 关于php中foreach循环地址符及变量应注意的问题
- java foreach循环中调用remove 抛出java.util.ConcurrentModificationException