Remarque: je connais la Iterator#remove()
méthode.
Dans l'exemple de code suivant, je ne comprends pas pourquoi la méthode List.remove
in main
lève ConcurrentModificationException
, mais pas dans la remove
méthode.
public class RemoveListElementDemo {
private static final List<Integer> integerList;
static {
integerList = new ArrayList<Integer>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
}
public static void remove(Integer toRemove) {
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
public static void main(String... args) {
remove(Integer.valueOf(2));
Integer toRemove = Integer.valueOf(3);
for(Integer integer : integerList) {
if(integer.equals(toRemove)) {
integerList.remove(integer);
}
}
}
}
java
list
concurrentmodification
foreach
Bhesh Gurung
la source
la source
Iterator#remove()
. Pourquoi le faites-vous de cette façon?ConcurrentModificationException
et l'autre non.return;
dans la boucle.Réponses:
Voici pourquoi: Comme il est dit dans le Javadoc:
Cette vérification se fait dans la
next()
méthode de l'itérateur (comme vous pouvez le voir par le stacktrace). Mais nous n'atteindrons lanext()
méthode que si elle esthasNext()
livrée true, ce qui est appelé par le for each pour vérifier si la limite est respectée. Dans votre méthode remove, lorsque voushasNext()
vérifiez s'il a besoin de retourner un autre élément, il verra qu'il a renvoyé deux éléments, et maintenant, après qu'un élément a été supprimé, la liste ne contient que deux éléments. Donc tout est pêche et nous en avons terminé avec les itérations. La vérification des modifications simultanées n'a pas lieu, car elle est effectuée dans lanext()
méthode qui n'est jamais appelée.Ensuite, nous arrivons à la deuxième boucle. Après avoir supprimé le deuxième nombre, la méthode hasNext vérifiera à nouveau si elle peut renvoyer plus de valeurs. Il a déjà renvoyé deux valeurs, mais la liste n'en contient plus qu'une. Mais le code ici est:
1! = 2, nous continuons donc à la
next()
méthode, qui se rend compte maintenant que quelqu'un a joué avec la liste et déclenche l'exception.J'espère que cela clarifie votre question.
Résumé
List.remove()
ne lancera pasConcurrentModificationException
lorsqu'il supprime l'avant-dernier élément de la liste.la source
Une façon de le gérer consiste à supprimer quelque chose d'une copie d'une
Collection
(et non de la collection elle-même), le cas échéant.Clone
la collection originale pour en faire une copie via un fichierConstructor
.Pour votre cas spécifique, tout d'abord, je ne pense pas que ce
final
soit une façon de procéder étant donné que vous avez l'intention de modifier la liste après la déclarationPensez également à modifier une copie au lieu de la liste d'origine.
la source
La méthode forward / iterator ne fonctionne pas lors de la suppression d'éléments. Vous pouvez supprimer l'élément sans erreur, mais vous obtiendrez une erreur d'exécution lorsque vous tenterez d'accéder aux éléments supprimés. Vous ne pouvez pas utiliser l'itérateur car, comme le montre insistant, cela provoquera une ConcurrentModificationException, utilisez donc une boucle for régulière à la place, mais revenez en arrière.
Une solution:
Parcourez le tableau dans l'ordre inverse si vous souhaitez supprimer un élément de liste. En revenant simplement dans la liste, vous évitez de visiter un élément qui a été supprimé, ce qui supprime l'exception.
la source
Cet extrait de code lèvera toujours une ConcurrentModificationException.
La règle est "Vous ne pouvez pas modifier (ajouter ou supprimer des éléments de la liste) tout en l'itérant à l'aide d'un itérateur (ce qui se produit lorsque vous utilisez une boucle for-each)".
JavaDocs:
Les itérateurs renvoyés par les méthodes iterator et listIterator de cette classe sont très rapides: si la liste est modifiée structurellement à tout moment après la création de l'itérateur, de quelque manière que ce soit, sauf par les propres méthodes remove ou add de l'itérateur, l'itérateur lancera une ConcurrentModificationException.
Par conséquent, si vous souhaitez modifier la liste (ou toute collection en général), utilisez iterator, car il est alors conscient des modifications et donc celles-ci seront gérées correctement.
J'espère que cela t'aides.
la source
J'ai eu le même problème mais au cas où j'ajouterais un élément dans la liste itérée. Je l'ai fait de cette façon
Maintenant, tout se passe bien car vous ne créez pas d'itérateur sur votre liste, vous l'itérez "manuellement". Et la condition
i < integerList.size()
ne vous trompera jamais car lorsque vous supprimez / ajoutez quelque chose dans la taille de la liste, décrémentez / incrémentez.J'espère que cela aide, pour moi, c'était la solution.
la source
Si vous utilisez des collections de copie sur écriture, cela fonctionnera; cependant, lorsque vous utilisez list.iterator (), l'itérateur retourné référencera toujours la collection d'éléments telle qu'elle était lorsque (comme ci-dessous) list.iterator () a été appelée, même si un autre thread modifie la collection. Toutes les méthodes de mutation appelées sur un Iterator ou ListIterator basé sur la copie sur écriture (comme ajouter, définir ou supprimer) lèveront une exception UnsupportedOperationException.
la source
Cela fonctionne bien sur Java 1.6
~% javac RemoveListElementDemo.java
~% java RemoveListElementDemo
~% cat RemoveListElementDemo.java
~%
la source
Dans mon cas, je l'ai fait comme ceci:
la source
Remplacez Iterator
for each
parfor loop
pour résoudre.Et la raison est:
- Documents Java référencés.
la source
Vérifiez votre code man ...
Dans la méthode principale, vous essayez de supprimer le 4ème élément qui n'est pas là et donc l'erreur. Dans la méthode remove (), vous essayez de supprimer le 3ème élément qui est là et donc aucune erreur.
la source
2
et3
ne sont pas des indices pour la liste, mais des éléments. Les deux logiques de suppression vérifientequals
les éléments de la liste, et non l'index des éléments. De plus, s'il était lié à un index, ce ne le seraitIndexOutOfBoundsException
pasConcurrentModificationException
.