Frage Fast-fail - Ausnahme tritt nur beim Hinzufügen eines Elements auf, nicht beim Entfernen


Schnell-Fehler : Das heißt, wenn sie erkennen Da sich die Sammlung seit Beginn der Iteration geändert hat, werfen sie das Häkchen aus ConcurrentModificationException.

Ich habe ein Testbeispiel geschrieben, um dies zu demonstrieren:

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

die Ausgabe ist:

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)

was erwartet wird. Wenn ein Element jedoch entfernt wird, wird die Ausnahme nicht ausgelöst:

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

Ausgabe:

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

Warum das? In beiden Fällen wird die Liste geändert.


6
2017-10-28 12:08


Ursprung


Antworten:


Der Punkt ist, dass es nicht ist hasNext() das prüft auf Änderung, aber next(). In Ihrem "Entfernen" -Szenario unterdrücken Sie die next Rufen Sie das würde werfen, weil es kein nächstes Element gibt.

Wenn du am Anfang drei Elemente hättest, würde das Entfernen von einem führen hasNext "wahr" sein. Dann das Folgende next wird die erwartete Ausnahme auslösen.

Der JavaDoc weist darauf hin, dass die "fail-fast" -Funktionalität auf der Basis von "bestem Aufwand" funktioniert und dass sie nur zum Erkennen von Fehlern verwendet werden soll, anstatt wirklich davon abhängig zu sein, damit sich das Programm korrekt verhält. Offensichtlich wegen der Nebenwirkungen wie dieser.


1
2017-10-28 13:21



ConcurrentModificationException werfen, können Sie während der Iteration einige Änderungen in der Liste vornehmen.

Wenn Sie nach der Änderung in der Liste während der Iteration versuchen, mit iterator auf next () oder remove () zuzugreifen, dann überprüfen Sie den modCount und expectedModCount und count ist nicht dasselbe wie throw ConcurrentModificationException .

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

0
2017-10-28 12:58