我正在使用下面的代码测试集合的ConcurrentModificationException:
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
for (String s : list) {
// if (s.equals("a")) { // ConcurrentModificationException!
if (s.equals("b")) { // -->> Magic number, NO Exception, Why?
// if (s.equals("c")) { // ConcurrentModificationException!
list.remove(s);
}
}
System.out.println(list);
}我不明白为什么删除"b“是可以的,但其他NG呢?
发布于 2014-08-28 09:46:46
首先要知道的是(如JLS中所述)以下增强的for循环:
for (String s : list) {
// Do something with s
}相当于:
for (Iterator<String> it = list.iterator(); it.hasNext();) {
String s = it.next();
// Do something with s
}如果您查看AbstractList中迭代器的实现,您将看到:
hasNext()不检查并发修改,只检查我们是否在列表的末尾,使用它的大小:
公共布尔值hasNext() {返回游标!= size();}next()所做的第一件事是调用checkForComodification(),查看在迭代过程中是否修改了列表:
公共e(){ checkForComodification();尝试{e=get(游标);lastRet = cursor++;返回next;} catch (IndexOutOfBoundsException e) { checkForComodification();抛出新的NoSuchElementException();}ConcurrentModificationException(){ if (modCount != expectedModCount)抛出新的ConcurrentModificationException()};因此,当您迭代和删除列表的倒数第二个元素时,下一个指令将是对hasNext()的调用,它将返回false,因为删除一个元素会导致列表的大小减少一个,并且您的迭代将停止而不调用next()并抛出一个Exception。
顺便说一句,所有这些只是一个实现细节,您不应该依赖它,因为它可能会改变,并且在迭代时使用it.remove()从列表中删除元素。
https://stackoverflow.com/questions/25545242
复制相似问题