list执行remove和add方法时,报java.util.ConcurrentModificationException的原因

最近的工作中,遇到一个问题:对一个List进行遍历的时候将其中的元素删除掉,结果报java.util.ConcurrentModificationException,通过查看源码,得知原因了。

在ArrayList中的remove方法代码如下:

publicboolean remove(Object o) {

if (o ==null) {

for (int index =0; index < size; index++)

if (elementData[index] ==null) {

fastRemove(index);

returntrue;

}

}else {

for (int index =0; index < size; index++)

if (o.equals(elementData[index])) {

fastRemove(index);

returntrue;

}

}

returnfalse;

}

privatevoid fastRemove(int index) {

modCount++;//只增加了modCount

....

}

我们接着看看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();
}
}
}

所以,产生ConcurrentModificationException的原因就是:
执行remove(Object o)方法之后,modCount和expectedModCount不相等了。然后当代码执行到next()方法时,判断了checkForComodification(),发现两个数值不等,就抛出了该Exception。

解决的办法是:(列举其中一个解决办法)

System.out.println("-2-使用Iterator的remove");

list = test.buildList();

try {

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {

iterator.next();

iterator.remove();

}

} catch (Exception e) {

// java.lang.IllegalStateException

e.printStackTrace();

}

`java.util.ConcurrentModificationException` 是Java中的一个异常,通常在使用迭代器(Iterator)对集合(如List、Set、Map)进行遍历出现。它表示在遍历过程中,集合的内容发生了修改,导致迭代器检测到了并抛出异常。 这个异常通常有以下几个可能的原因: 1. 直接在遍历过程中对集合进行了增删操作:在使用迭代器遍历集合,如果直接对集合进行增删操作(如调用`add()`、`remove()`等方法),会导致迭代器的内部状态与集合的状态不一致,从而触发`ConcurrentModificationException`异常。 2. 多线程并发修改同一个集合:如果多个线程同对同一个集合进行修改操作,就可能引发`ConcurrentModificationException`异常。因为多线程并发修改同一个集合,无法保证迭代器的一致性。 3. 使用了不正确的迭代方式:在某些情况下,使用迭代器遍历集合的方式可能会导致`ConcurrentModificationException`异常。比如,在使用增强型for循环(foreach)遍历集合,如果在循环内部对集合进行了增删操作,就可能出现异常。 解决这个异常的常见方法是使用`Iterator`的安全删除方法`remove()`来进行元素的删除操作,或者使用并发安全的集合类(如`ConcurrentHashMap`、`CopyOnWriteArrayList`)来替代普通的集合类。此外,还可以使用`synchronized`关键字或`Lock`机制来对集合的操作进行同步,以避免并发修改问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值