1.写出下面的输出结果
public class test{
public static void main(String [] args)
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10; i++)
{
list.add(String.valueOf(i));
}
for(String s :
list){
if(s.equals("3")){
list.remove(s);
}
}
System.out.println(list.size());
}
}
正确的输出:发生了并发的错误
java.util.ConcurrentModificationException
at
java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown
Source)
at
test.main(test.java:35)
在这里for(String s : list){}的实质还是Iterator接口。
上面这段代码等价于下面:
Iterator<String> iterator =
list.iterator();
while(iterator.hasNext()){
String itString =
(String)iterator.next();
if (itString.equals("3")) {
list.remove(itString);
--这里会报错
//iterator.remove();---这里不会报错
}
}
所以我们来看看 list.iterator();的源码就知道为什么了
public Iterator<E> iterator() {
return new Itr();
}
/**
* An optimized version of AbstractList.Itr
*/
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;
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next()
{
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];
}
public void remove() {
if (lastRet < 0)
throw new
IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor =
lastRet;
lastRet = -1;
expectedModCount = modCount;
}
catch (IndexOutOfBoundsException ex) {
throw new
ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount !=
expectedModCount)
throw new
ConcurrentModificationException();
}
}
从源码上我们可以看出,当我们调用next()方法的时候有一个检查modCount != expectedModCount;然后我们再来看看ArrayList的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 remove method that skips bounds checking and does not
*
return the value removed.
*/
private void fastRemove(int index)
{
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
}
从上面的代码中可以看出当我们进行remove的时候modeCount的值发生了变化,这就导致和expectedModCount的值相等了,故报错。
从源码中我们还得知,在clear方法,add方法,addAll方法,removeRange方法时都会导致modeCount的值发生变化。
所以当我们想在循环中对List进行删除时不能用List的remove*方法。但是可以用iterator.remove();从上面的源码中我们可以知道这个方法中进行了
expectedModCount=ModCount对expectedModCount重新赋值。
JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误,布布扣,bubuko.com
JAVA循环迭代中删除或添加集合数据报java.util.ConcurrentModificationException错误