Fast-fail-исключение происходит только при добавлении элемента, а не при удалении

Fast-Fail : это означает, что, если они обнаруживают что коллекция изменилась с момента начала итерации, они бросают непроверенный ConcurrentModificationException.

я написал тестовый пример demonsterate это:

    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");
    }

выход:

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)

, который ожидается. Однако при удалении элемента исключение не создается:

    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);
    }

выход:

list before: [Hi, Buy]
list after: [Buy]

почему это? в обоих случаях список изменяется.

2 ответов


дело в том, что это не hasNext() Это проверяет на модификацию, но next(). В сценарии "удалить" вы подавляете next вызов, который будет бросать, потому что нет следующего элемента.

если у вас было 3 элемента в начале, удаление одного приведет к hasNext быть "истинным". Затем следующее next выдаст ожидаемое исключение.

JavaDoc указывает, что функциональность "fail-fast" работает на основе "лучших усилий" и что она должна быть используется только для обнаружения ошибок, а не действительно зависит от него, чтобы программа вела себя правильно. Очевидно, из-за таких побочных эффектов.


ConcurrentModificationException будет бросать, вы можете внести некоторые изменения в список во время итерации.

после выполнения модификации в списке во время итерации, если вы пытаетесь получить доступ к следующему() или удалить () с помощью итератора, то он проверяет modCount и expectedModCount и count не то же самое, то он бросает ConcurrentModificationException .

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }