J'ai le code suivant:
private String toString(List<DrugStrength> aDrugStrengthList) {
StringBuilder str = new StringBuilder();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
Lorsque j'essaie de l'exécuter, j'obtiens ConcurrentModificationException
. Quelqu'un peut-il expliquer pourquoi cela se produit, même si le code s'exécute dans le même thread? Et comment pourrais-je l'éviter?
Vous ne pouvez pas supprimer de la liste si vous le parcourez avec "pour chaque" boucle. Vous pouvez utiliser Iterator
. Remplacer:
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
aDrugStrengthList.remove(aDrugStrength);
}
}
Avec:
for (Iterator<DrugStrength> it = aDrugStrengthList.iterator(); it.hasNext(); ) {
DrugStrength aDrugStrength = it.next();
if (!aDrugStrength.isValidDrugDescription()) {
it.remove();
}
}
Comme le disent les autres réponses, vous ne pouvez pas supprimer un élément d'une collection sur laquelle vous effectuez une itération. Vous pouvez contourner ce problème en utilisant explicitement un Iterator
et en y supprimant l'élément.
Iterator<Item> iter = list.iterator();
while(iter.hasNext()) {
Item blah = iter.next();
if(...) {
iter.remove(); // Removes the 'current' item
}
}
J'aime les ordres inverses pour les boucles tels que:
int size = list.size();
for (int i = size - 1; i >= 0; i--) {
if(remove){
list.remove(i);
}
}
car il ne nécessite pas l'apprentissage de nouvelles structures de données ou de classes.
il devrait y avoir une implémentation simultanée de l'interface de liste prenant en charge une telle opération.
essayez Java.util.concurrent.CopyOnWriteArrayList.class
En effectuant une itération dans la boucle, vous essayez de modifier la valeur de liste dans l'opération remove (). Cela entraînera ConcurrentModificationException.
Suivez le code ci-dessous, qui réalisera ce que vous voulez et ne lancera aucune exception.
private String toString(List aDrugStrengthList) {
StringBuilder str = new StringBuilder();
List removalList = new ArrayList();
for (DrugStrength aDrugStrength : aDrugStrengthList) {
if (!aDrugStrength.isValidDrugDescription()) {
removalList.add(aDrugStrength);
}
}
aDrugStrengthList.removeAll(removalList);
str.append(aDrugStrengthList);
if (str.indexOf("]") != -1) {
str.insert(str.lastIndexOf("]"), "\n " );
}
return str.toString();
}
Nous pouvons utiliser des classes de collection simultanées pour éviter la ConcurrentModificationException lors d'une itération sur une collection, par exemple CopyOnWriteArrayList au lieu de ArrayList.
Vérifiez ce post pour ConcurrentHashMap
http://www.journaldev.com/122/hashmap-vs-concurrenthashmap-%E2%80%93-example-and-exploring-iterator