En parcourant une liste, je voudrais supprimer un élément d’une liste en fonction d’une condition. Voir le code ci-dessous.
Cela me donne une exception ConcurrentModification
.
for (Object a : list) {
if (a.getXXX().equalsIgnoreCase("AAA")) {
logger.info("this is AAA........should be removed from the list ");
list.remove(a);
}
}
Comment cela peut-il être fait?
Vous devez utiliser Iterator
et appeler remove()
sur iterator
au lieu d'utiliser la boucle for
.
for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
String a = iter.next();
if (...) {
iter.remove();
}
}
En supposant de plus que la liste est constituée de chaînes. Comme déjà répondu, une list.iterator()
est nécessaire. Le listIterator peut aussi faire un peu de navigation.
Vous ne pouvez pas le faire car vous le faites déjà.
Afin d'éviter cette situation, utilisez Iterator, qui vous garantit de supprimer l'élément de la liste en toute sécurité ...
List<Object> objs;
Iterator<Object> i = objs.iterator();
while (i.hasNext()) {
Object o = i.next();
//some condition
i.remove();
}
Vous ne pouvez pas et ne devriez pas modifier une liste en la parcourant. Vous pouvez résoudre ce problème en enregistrant temporairement les objets à supprimer:
List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
toRemove.add(a);
}
}
list.removeAll(toRemove);
Outre toutes les excellentes solutions proposées ici, j'aimerais proposer une solution différente.
Je ne sais pas si vous êtes libre d'ajouter des dépendances, mais si vous le pouviez, vous pouvez ajouter le https://code.google.com/p/guava-libraries/ en tant que dépendance. Cette bibliothèque ajoute la prise en charge de nombreuses opérations fonctionnelles de base à Java et permet de travailler avec des collections beaucoup plus facilement et plus lisiblement.
Dans le code, j'ai remplacé le type de la liste par T, car je ne sais pas à quoi votre liste est dactylographiée.
Ce problème peut être résolu comme ceci avec la goyave:
List<T> filteredList = new Arraylist<>(filter(list, not(XXX_EQUAL_TO_AAA)));
Et ailleurs, vous définissez ensuite XXX_EQUAL_TO_AAA comme suit:
public static final Predicate<T> XXX_EQUAL_TO_AAA = new Predicate<T>() {
@Override
public boolean apply(T input) {
return input.getXXX().equalsIgnoreCase("AAA");
}
}
Cependant, c'est probablement exagéré dans votre situation. C'est simplement quelque chose qui devient de plus en plus puissant à mesure que vous travaillez avec des collections.
Ohw, vous avez également besoin de ces importations statiques:
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Collections2.filter;
//first find out the removed ones
List removedList = new ArrayList();
for(Object a: list){
if(a.getXXX().equalsIgnoreCase("AAA")){
logger.info("this is AAA........should be removed from the list ");
removedList.add(a);
}
}
list.removeAll(removedList);