ConcurrentModificationException并发修改异常
#ConcurrentModificationException
在学习List集合的时候,在遍历的时候修改元素,发现报了错误。
List<String> l=new ArrayList<String>();
l.add("北京");
l.add("南京");
l.add("东京");
Iterator<String> it=l.iterator();
while(it.hasNext()){
String ss=it.next();
if(ss.equals("南京"))
{
l.add("上海");
}
System.out.println(ss);
}
报错
Exception in thread “main” java.util.ConcurrentModificationException
at java.util.ArrayList
I
t
r
.
c
h
e
c
k
F
o
r
C
o
m
o
d
i
f
i
c
a
t
i
o
n
(
A
r
r
a
y
L
i
s
t
.
j
a
v
a
:
909
)
a
t
j
a
v
a
.
u
t
i
l
.
A
r
r
a
y
L
i
s
t
Itr.checkForComodification(ArrayList.java:909) at java.util.ArrayList
Itr.checkForComodification(ArrayList.java:909)atjava.util.ArrayListItr.next(ArrayList.java:859)
at com.neu.test4.ListDemo.main(ListDemo.java:32)
原因就出在32行上的next方法出了问题,集合的迭代器是不允许在遍历的时候对集合集合进行操作的。
我们来看看API是怎么说的
看源码:因为我们的集合l是ArrayList的对象,且使用了里面的add()方法和Iterator方法。
public boolean add(E e) {
modCount++;//5、而我们在操作时,实际修改次数会变化,但是预期修改次数不会变化。这就让我们在checkForComodification方法里比较两个值的时候不同,就会抛出并发修改异常。
//而我们的modCount这个值来自于ArrayList,但是我们查看ArrayList却没有,那是因为ArrayList继承了AbstractList这个抽下类,而抽象类里面就有这个值。如下
add(e, elementData, size);
return true;
}
protected transient int modCount = 0;//6、AbstractList里面的。一开始值为0,然后在调用next,会判断,可是我们在next方法里做了用了add方法,而add方法会修改modCount的值。造成异常。
public Iterator<E> iterator() {
return new Itr();
}
Iterator有返回了一个Itr对象。(在报错里面也可以看到)看next方法。
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;//4、而在Itr类里面,已经将实际修改次数赋值给了期望修改次数。
@SuppressWarnings("unchecked")
public E next() {//1、在进入next方法时,会调用checkForComodification方法。如下
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
final void checkForComodification() {
if (modCount != expectedModCount)//2、而这个方法首先会比较两个值:modCount(实际修改集合的次数)和expectedModCount(预期修改集合的次数)。
throw new ConcurrentModificationException();//3、判断,如果这两个值不相等,就会抛出我们所看到的ConcurrentModificationException异常。
}
解决办法
可以用for循环遍历集合呀。哈哈哈哈,这样就不会报错了。