Ich habe eine ArrayList, über die ich iterieren möchte. Während ich darüber iteriere, muss ich gleichzeitig Elemente entfernen. Offensichtlich wirft dies eine java.util.ConcurrentModificationException
.
Was ist die beste Vorgehensweise, um dieses Problem zu lösen? Soll ich zuerst die Liste klonen?
Ich entferne die Elemente nicht in der Schleife selbst, sondern in einem anderen Teil des Codes.
Mein Code sieht folgendermaßen aus:
public class Test() {
private ArrayList<A> abc = new ArrayList<A>();
public void doStuff() {
for (A a : abc)
a.doSomething();
}
public void removeA(A a) {
abc.remove(a);
}
}
a.doSomething
könnte anrufen Test.removeA()
;
Antworten:
Zwei Optionen:
originalList.removeAll(valuesToRemove)
am Ende aufremove()
Methode auf dem Iterator selbst. Beachten Sie, dass dies bedeutet, dass Sie die erweiterte for-Schleife nicht verwenden können.Als Beispiel für die zweite Option entfernen Sie Zeichenfolgen mit einer Länge von mehr als 5 aus einer Liste:
quelle
Aus den JavaDocs der ArrayList
quelle
Sie versuchen, den Wert aus der Liste in der erweiterten "for-Schleife" zu entfernen, was nicht möglich ist, selbst wenn Sie einen Trick anwenden (den Sie in Ihrem Code ausgeführt haben). Besser ist es, die Iterator-Ebene zu codieren, wie hier empfohlen.
Ich frage mich, wie die Leute keinen traditionellen Loop-Ansatz vorgeschlagen haben.
Das funktioniert auch.
quelle
Sie sollten das Array wirklich nur auf herkömmliche Weise durchlaufen
Jedes Mal, wenn Sie ein Element aus der Liste entfernen, werden die nachfolgenden Elemente vorwärts verschoben. Solange Sie keine anderen Elemente als das iterierende ändern, sollte der folgende Code funktionieren.
quelle
In Java 8 können Sie die Sammlungsschnittstelle verwenden und dazu die Methode removeIf aufrufen:
Weitere Informationen finden Sie hier
quelle
Führen Sie die Schleife wie gewohnt aus. Dies
java.util.ConcurrentModificationException
ist ein Fehler in Bezug auf die Elemente, auf die zugegriffen wird.Also versuche:
quelle
java.util.ConcurrentModificationException
indem Sie nichts von der Liste entfernt haben. Tricky. :) Sie können dies nicht wirklich "den normalen Weg" nennen, um eine Liste zu iterieren.Während Sie die Liste durchlaufen, ist es möglich, das Element zu entfernen. Lassen Sie unten meine Beispiele sehen,
Ich habe die oben genannten Namen der Array-Liste. Und ich möchte den Namen "def" aus der obigen Liste entfernen,
Der obige Code löst die ConcurrentModificationException aus Ausnahme aus, da Sie die Liste während der Iteration ändern.
Um den Namen "def" auf diese Weise aus Arraylist zu entfernen,
Mit dem obigen Code können wir über den Iterator den Namen "def" aus der Arrayliste entfernen und versuchen, das Array zu drucken. Die folgende Ausgabe wird angezeigt.
Ausgabe: [abc, ghi, xyz]
quelle
Eine Möglichkeit besteht darin, die
removeA
Methode dahingehend zu ändern :Dies würde jedoch bedeuten, dass Sie
doSomething()
in der Lage sein sollten, dasiterator
an dieremove
Methode weiterzugeben . Keine sehr gute Idee.Können Sie dies in zwei Schritten tun: Markieren Sie in der ersten Schleife, wenn Sie die Liste durchlaufen, anstatt die ausgewählten Elemente zu entfernen, diese als gelöscht . Dazu können Sie diese Elemente (flache Kopie) einfach in ein anderes kopieren
List
.Sobald Ihre Iteration abgeschlossen ist, führen Sie einfach
removeAll
alle Elemente in der zweiten Liste aus der ersten Liste aus.quelle
Hier ist ein Beispiel, in dem ich eine andere Liste verwende, um die zu entfernenden Objekte hinzuzufügen. Anschließend verwende ich stream.foreach, um Elemente aus der ursprünglichen Liste zu entfernen:
quelle
Verwenden Sie für jede Schleife normal für Schleife. Mit dem folgenden Code wird beispielsweise das gesamte Element in der Array-Liste entfernt, ohne dass eine java.util.ConcurrentModificationException angegeben wird. Sie können die Bedingung in der Schleife entsprechend Ihrem Anwendungsfall ändern.
quelle
Mach so etwas einfach:
quelle
Eine alternative Java 8-Lösung mit Stream:
In Java 7 können Sie stattdessen Guava verwenden:
Beachten Sie, dass das Guava-Beispiel zu einer unveränderlichen Liste führt, die möglicherweise Ihren Wünschen entspricht oder nicht.
quelle
Sie können auch CopyOnWriteArrayList anstelle einer ArrayList verwenden. Dies ist der neueste empfohlene Ansatz ab JDK 1.5.
quelle
In meinem Fall funktioniert die akzeptierte Antwort nicht. Sie stoppt die Ausnahme, verursacht jedoch einige Inkonsistenzen in meiner Liste. Die folgende Lösung funktioniert perfekt für mich.
In diesem Code habe ich die zu entfernenden Elemente in einer anderen Liste hinzugefügt und dann die
list.removeAll
Methode verwendet, um alle erforderlichen Elemente zu entfernen.quelle
"Soll ich zuerst die Liste klonen?"
Dies ist die einfachste Lösung. Entfernen Sie sie aus dem Klon und kopieren Sie sie nach dem Entfernen zurück.
Ein Beispiel aus meinem Rummikub-Spiel:
quelle
stones = (...) clone.clone();
überflüssig ist. Würde nichtstones = clone;
das gleiche tun?stones
. Auf diese Weise brauchen Sie nicht einmal dieclone
Variable:for (Stone stone : (ArrayList<Stone>) stones.clone()) {...
Wenn Sie alle Elemente aus der Liste entfernen möchten, können Sie jedes Element durchlaufen und dann Folgendes aufrufen:
quelle
Ich komme spät an, ich weiß, aber ich beantworte dies, weil ich denke, dass diese Lösung einfach und elegant ist:
All dies dient zum Aktualisieren von einer Liste in eine andere, und Sie können alles aus nur einer Liste erstellen. Bei der Methodenaktualisierung überprüfen Sie beide Listen und können Elemente zwischen Listen löschen oder hinzufügen. Dies bedeutet, dass beide Listen immer die gleiche Größe haben
quelle
Verwenden Sie Iterator anstelle von Array List
Lassen Sie eine Menge in einen Iterator mit Typübereinstimmung konvertieren
Gehen Sie zum nächsten Element und entfernen Sie es
Hier ist es wichtig, zum nächsten zu wechseln, da der Index zum Entfernen des Elements erforderlich ist.
quelle
Was ist mit
quelle
Fügen Sie einfach eine Pause nach Ihrer ArrayList.remove (A) -Anweisung hinzu
quelle