J'ai une ArrayList sur laquelle je veux répéter. Tout en itérant dessus, je dois supprimer des éléments en même temps. De toute évidence, cela jette un java.util.ConcurrentModificationException
.
Quelle est la meilleure pratique pour gérer ce problème? Dois-je d'abord cloner la liste?
Je supprime les éléments non pas dans la boucle elle-même mais dans une autre partie du code.
Mon code ressemble à ceci:
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
pourrait appeler Test.removeA()
;
Réponses:
Deux options:
originalList.removeAll(valuesToRemove)
à la finremove()
méthode sur l'itérateur lui-même. Notez que cela signifie que vous ne pouvez pas utiliser la boucle for améliorée.Comme exemple de la deuxième option, supprimer toutes les chaînes d'une longueur supérieure à 5 d'une liste:
la source
À partir des JavaDocs de la ArrayList
la source
Vous essayez de supprimer la valeur de la liste dans la boucle avancée "for", ce qui n'est pas possible, même si vous appliquez une astuce (ce que vous avez fait dans votre code). Le meilleur moyen est de coder le niveau de l'itérateur comme indiqué ici.
Je me demande comment les gens n'ont pas suggéré l'approche traditionnelle de la boucle.
Cela fonctionne aussi.
la source
Vous devez vraiment simplement réitérer le tableau de la manière traditionnelle
Chaque fois que vous supprimez un élément de la liste, les éléments suivants seront repoussés. Tant que vous ne modifiez pas d'autres éléments que l'itération, le code suivant devrait fonctionner.
la source
Dans Java 8, vous pouvez utiliser l'interface de collecte et le faire en appelant la méthode removeIf:
Plus d'informations peuvent être trouvées ici
la source
Faites la boucle normalement,
java.util.ConcurrentModificationException
c'est une erreur liée aux éléments auxquels vous accédez.Alors essayez:
la source
java.util.ConcurrentModificationException
en ne supprimant rien de la liste. Rusé. :) Vous ne pouvez pas vraiment appeler cela "la voie normale" pour parcourir une liste.Lors de l'itération de la liste, si vous souhaitez supprimer l'élément est possible. Voyons ci-dessous mes exemples,
J'ai les noms ci-dessus de la liste des tableaux. Et je veux supprimer le nom "def" de la liste ci-dessus,
Le code ci-dessus lève l' exception ConcurrentModificationException car vous modifiez la liste lors de l'itération.
Donc, pour supprimer le nom "def" d'Arraylist en procédant de cette façon,
Le code ci-dessus, via l'itérateur, nous pouvons supprimer le nom "def" de la liste Arraylist et essayer d'imprimer le tableau, vous verrez la sortie ci-dessous.
Sortie: [abc, ghi, xyz]
la source
Une option consiste à modifier la
removeA
méthode en ceci -Mais cela signifierait que vous
doSomething()
devriez pouvoir passeriterator
à laremove
méthode. Ce n'est pas une bonne idée.Pouvez-vous le faire en deux étapes: dans la première boucle lorsque vous parcourez la liste, au lieu de supprimer les éléments sélectionnés, marquez- les comme devant être supprimés . Pour cela, vous pouvez simplement copier ces éléments (copie superficielle) dans un autre
List
.Ensuite, une fois votre itération terminée, faites simplement a
removeAll
partir de la première liste tous les éléments de la seconde liste.la source
Voici un exemple où j'utilise une liste différente pour ajouter les objets à supprimer, puis j'utilise stream.foreach pour supprimer des éléments de la liste d'origine:
la source
Au lieu d'utiliser Pour chaque boucle, utilisez la boucle normale. par exemple, le code ci-dessous supprime tous les éléments de la liste de tableaux sans donner java.util.ConcurrentModificationException. Vous pouvez modifier la condition dans la boucle en fonction de votre cas d'utilisation.
la source
Faites quelque chose de simple comme ceci:
la source
Une solution alternative Java 8 utilisant stream:
Dans Java 7, vous pouvez utiliser Guava à la place:
Notez que l'exemple de Guava se traduit par une liste immuable qui peut ou non être ce que vous voulez.
la source
Vous pouvez également utiliser CopyOnWriteArrayList au lieu d'une ArrayList. Il s'agit de la dernière approche recommandée à partir de JDK 1.5.
la source
Dans mon cas, la réponse acceptée ne fonctionne pas, elle arrête l'exception mais elle provoque une incohérence dans ma liste. La solution suivante fonctionne parfaitement pour moi.
Dans ce code, j'ai ajouté les éléments à supprimer, dans une autre liste, puis utilisé la
list.removeAll
méthode pour supprimer tous les éléments requis.la source
"Dois-je d'abord cloner la liste?"
Ce sera la solution la plus simple, supprimez du clone et recopiez le clone après la suppression.
Un exemple de mon jeu de rummikub:
la source
stones = (...) clone.clone();
soit superflu. Ne ferait pas destones = clone;
même?stones
. De cette façon, vous n'avez même pas besoin de laclone
variable:for (Stone stone : (ArrayList<Stone>) stones.clone()) {...
Si votre objectif est de supprimer tous les éléments de la liste, vous pouvez parcourir chaque élément, puis appeler:
la source
J'arrive en retard je sais mais je réponds à cela car je pense que cette solution est simple et élégante:
Tout cela est pour la mise à jour d'une liste à l'autre et vous pouvez tout faire à partir d'une seule liste et dans la mise à jour de la méthode, vous vérifiez les deux listes et pouvez effacer ou ajouter des éléments entre la liste. Cela signifie que les deux affichent toujours la même taille
la source
Utiliser Iterator au lieu de Array List
Faire convertir un ensemble en itérateur avec correspondance de type
Et passer à l'élément suivant et supprimer
Le passage au suivant est important ici car il devrait prendre l'index pour supprimer l'élément.
la source
Qu'en est-il de
la source
Ajoutez simplement une pause après votre instruction ArrayList.remove (A)
la source