如果我取消注释行list.add(" 3"),则抛出ConcurrentModificationException。对于两个元素,它工作正常,并抛出1或3个元素异常?对此行为的任何解释?
import java.util.*;
public class ConException {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
//list.add("3");
for(String x: list){
list.remove("1");
}
System.out.println(list);
}
}
答案 0 :(得分:0)
您在迭代时无法更改列表
因此,您无法在list.remove("1")
循环内拨打for (String x: list)
删除循环,只需删除“1”元素。
如果要删除所有“1”元素,可以通过以下方式执行此操作:
while (list.remove("1")) {}
修改强>
这是用于for循环的ArrayListIterator
类的反编译代码。在每次迭代后调用next
方法,可以抛出ConcurrentModificationException
private class ArrayListIterator implements Iterator<E> {
/** Number of elements remaining in this iteration */
private int remaining = size;
/** Index of element that remove() would remove, or -1 if no such elt */
private int removalIndex = -1;
/** The expected modCount value */
private int expectedModCount = modCount;
public boolean hasNext() {
return remaining != 0;
}
@SuppressWarnings("unchecked") public E next() {
ArrayList<E> ourList = ArrayList.this;
int rem = remaining;
if (ourList.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (rem == 0) {
throw new NoSuchElementException();
}
remaining = rem - 1;
return (E) ourList.array[removalIndex = ourList.size - rem];
}
public void remove() {
Object[] a = array;
int removalIdx = removalIndex;
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
if (removalIdx < 0) {
throw new IllegalStateException();
}
System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
a[--size] = null; // Prevent memory leak
removalIndex = -1;
expectedModCount = ++modCount;
}
}
在以下情况下,我们会从next
方法抛出异常:
if (ourList.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
我们的modCount
变量在remove
次迭代时已更改,因此下一次next
调用将失败。
答案 1 :(得分:0)
请阅读ConcurrentModificationException的java文档 https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html
在您的情况下,只有在ArrayList中有2个元素时才会获得异常,在所有其他情况下,您会得到ConcurrentModificationException。
正如javaDoc声明的那样,它依赖于JRE确定是否正在进行任何并发修改,并且它不是保证确定相同的方法,正如javadoc中明确指出的那样。
请注意,通常情况下无法保证快速失败的行为 说话,在场的情况下不可能做出任何硬性保证 非同步并发修改