快速失败 - 只有在删除元素时才会发生异常

Sam*_*Sam 6 java collections concurrency

快速失败:意味着如果他们在迭代开始后检测到集合已经发生了变化,那么他们就会抛弃未经检查的东西 ConcurrentModificationException.

我写了一个测试示例来解决这个问题:

    String hi = "Hi";
    list.add(hi);
    list.add("Buy");
    System.out.println("list before: " + list);
    for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
        String string = iterator.next();
        list.add("Good");
    }
Run Code Online (Sandbox Code Playgroud)

输出是:

list before: [Hi, Buy]
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at thread.CollectionTest.main(CollectionTest.java:19)
Run Code Online (Sandbox Code Playgroud)

这是预料之中的.但是,删除元素时,不会抛出异常:

    List<String> list = new ArrayList<>();

    String hi = "Hi";
    list.add(hi);
    list.add("Buy");
    System.out.println("list before: " + list);
    for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
        String string = iterator.next();
        list.remove(hi);
    }
Run Code Online (Sandbox Code Playgroud)

输出:

list before: [Hi, Buy]
list after: [Buy]
Run Code Online (Sandbox Code Playgroud)

这是为什么?两种情况都修改了列表.

Fil*_*dor 1

关键是它不是hasNext()检查修改,而是检查next(). 在“删除”场景中,您会抑制next因没有下一个元素而引发的调用。

如果一开始有 3 个元素,则删除一个元素将导致结果为hasNext“true”。然后以下next将抛出预期的异常。

JavaDoc 指出,“快速失败”功能基于“尽力而为”的工作原理,并且它应该仅用于检测错误,而不是真正依赖它来使程序正确运行。显然是因为像这样的副作用。