list的数据遍历时的删除错误及其解决办法
Posted daqq
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了list的数据遍历时的删除错误及其解决办法相关的知识,希望对你有一定的参考价值。
在遍历list而且特定条件下需要删除刚刚遍历完的一个元素时调用的remove(object)会报如下错误:主要是因为Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性。是在于foreach方式遍历元素的时候,是生成iterator,然后使用iterator遍历。在生成iterator的时候,会保存一个expectedModCount参数,这个是生成iterator的时候List中修改元素的次数。如果你在遍历过程中删除元素,List中modCount就会变化,如果这个modCount和exceptedModCount不一致,就会抛出异常,这个是为了安全的考虑。
foreach的remove(Object)的源码:
-
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;
-
}没有对expectedModCount进行任何修改,导致expectedModCount和modCount不一致,抛出异常。iterear的remove()源码
-
public void remove() {
-
if (lastRet < 0)
-
throw new IllegalStateException();
-
checkForComodification();
-
-
-
try {
-
ArrayList.this.remove(lastRet);
-
cursor = lastRet;
-
lastRet = -1;
-
expectedModCount = modCount;//处理expectedModCount
-
} catch (IndexOutOfBoundsException ex) {
-
throw new ConcurrentModificationException();
-
}
-
}对expectedModCount重新做了赋值处理的。这样的话保持expectedModCount = modCount相等,就不会报出错了。
-
以上是关于list的数据遍历时的删除错误及其解决办法的主要内容,如果未能解决你的问题,请参考以下文章
ArrayList 使用 forEach 遍历时删除元素会报错吗?