250 votes

Comment éviter l'exception java.util.ConcurrentModificationException lors de l'itération et de la suppression d'éléments d'une ArrayList ?

J'ai une liste de tableaux que je veux parcourir par itération. Pendant cette itération, je dois supprimer des éléments en même temps. Évidemment, cela génère un java.util.ConcurrentModificationException .

Quelle est la meilleure pratique pour gérer ce problème ? Devrais-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() ;

3voto

Xlsx Points 183

Faites quelque chose de simple comme ça :

for (Object object: (ArrayList<String>) list.clone()) {
    list.remove(object);
}

3voto

Asad Choudhary Points 113

Dans mon cas, la réponse acceptée ne fonctionne pas, elle arrête l'exception mais provoque une certaine incohérence dans ma liste. La solution suivante fonctionne parfaitement pour moi.

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

for (String value: list) {
   if (value.length() > 5) { // your condition
       itemsToRemove.add(value);
   }
}
list.removeAll(itemsToRemove);

Dans ce code, j'ai ajouté les éléments à supprimer, dans une autre liste et ensuite utilisé list.removeAll pour supprimer tous les éléments requis.

2voto

Zsolt Sky Points 1

Une solution alternative en Java 8 utilisant stream :

        theList = theList.stream()
            .filter(element -> !shouldBeRemoved(element))
            .collect(Collectors.toList());

En Java 7, vous pouvez utiliser Guava à la place :

        theList = FluentIterable.from(theList)
            .filter(new Predicate<String>() {
                @Override
                public boolean apply(String element) {
                    return !shouldBeRemoved(element);
                }
            })
            .toImmutableList();

Notez que l'exemple de Guava donne une liste immuable, ce qui n'est pas forcément ce que vous voulez.

1voto

Pathikreet Points 13

Vous pouvez également utiliser CopyOnWriteArrayList au lieu d'une ArrayList. Il s'agit de la dernière approche recommandée à partir du JDK 1.5.

1voto

gachokaeric Points 66
for (A a : new ArrayList<>(abc)) {
    a.doSomething();
    abc.remove(a);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X