Java ConcurrentModificationException的幻数

Java ConcurrentModificationException的幻数,java,Java,我正在使用下面的代码测试集合的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) { // i

我正在使用下面的代码测试集合的
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);
}
publicstaticvoidmain(字符串[]args){
ArrayList=新建ArrayList();
列表。添加(“a”);
列表。添加(“b”);
列表。添加(“c”);
用于(字符串s:列表){
//如果(s.equals(“a”){//ConcurrentModificationException!
如果(s.equals(“b”){/-->>幻数,没有例外,为什么?
//如果(s.equals(“c”){//ConcurrentModificationException!
列表。删除;
}
}
系统输出打印项次(列表);
}

我不明白为什么删除“b”是可以的,但其他人不可以?

首先要知道的是(如中所述)以下增强的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
}
  • next()
    所做的第一件事是调用
    checkForComodification()
    查看列表是否在我们迭代时被修改:

    public E next() {
            checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
    }
    
    final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }
    
  • 因此,当您迭代并删除列表的倒数第二个元素时,下一条指令将调用
    hasNext()
    ,它将返回
    false
    ,因为删除一个元素会导致列表的大小减少一个,并且您的迭代将停止而不调用
    next()
    并引发
    异常


    顺便说一句,所有这些都只是一个实现细节,您不应该依赖它,因为它可能会更改,并且在您迭代时使用它从列表中删除元素。

    它应该抛出ConcurrentModificationException。您确定您没有在某个地方出错吗?不,我确定。我在JDK 7中进行了测试,在调试模式下运行它,并观察仔细一步,你就会明白为什么边缘值会抛出异常。更进一步,如果你也这样做
    list.add(“d”);
    ,你会注意到删除
    “c”
    也不会再抛出异常。非常感谢这个令人难以置信的回答Hey Florent,那么我可以说这个缺陷是在公共布尔hasNext()中吗{返回游标!=size;}
    public E next() {
            checkForComodification();
        try {
        E next = get(cursor);
        lastRet = cursor++;
        return next;
        } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
        }
    }
    
    final void checkForComodification() {
        if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    }