La source de l'erreur checkForComodification() peut être connue grâce à l'erreur signalée. Si vous souhaitez éviter les erreurs, vous devez conserver modCount != expectedModCount comme false . list.remove(Object) appellera la méthode fastRemove(int), et elle modifiera inévitablement modCount à ce moment-là, et une erreur se produira à ce moment-là. Iterator<String> iterator = list.iterator() ; L'implémentation de cette méthode consiste à renvoyer une classe interne Itr (cette classe est utilisée dans le processus d'itération), mais la raison pour laquelle cela iterator.remove() ne provoque pas d'erreurs est due à la relation entre cette méthode et L'implémentation consiste à vérifier ArrayList.this.remove avant de faire le checkForComodfication réel et à faire remove après expectedModCount = modCount afin qu'aucune erreur ne se produise.
Itr.removeMise en œuvre
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
S'il y a quelque chose qui ne va pas, veuillez le signaler @ChaCha哥 @puliuyinyi
Dans le cas d'un seul thread, lors de la suppression d'éléments lors du parcours de la liste, vous devez utiliser la méthode Remove d'Iterator au lieu de la méthode Remove de List, sinon une ConcurrentModificationException se produira. Imaginez simplement si un enseignant compte le nombre d'élèves dans toute la classe, et si les élèves ne respectent pas les règles et ne sortent pas et n'entrent pas, l'enseignant ne pourra certainement pas les compter.
Dans le cas du multi-threading, référez-vous à un de mes blogs : http://xxgblog.com/2016/04/02...
Tout d'abord, cela implique des opérations multi-thread. Iterator ne prend pas en charge les opérations multi-thread. La classe List maintiendra une variable modCount en interne pour enregistrer le nombre de modifications Exemple : code source ArrayList
protected transient int modCount = 0;
Chaque fois qu'un Iterator est généré, l'Iterator enregistrera le modCount. Chaque fois que la méthode next() est appelée, l'enregistrement sera comparé au modCount de la classe externe List. S'il s'avère inégal, un. une exception d'édition multithread sera levée.
Pourquoi fais-tu ça ? Je crois comprendre que vous avez créé un itérateur étroitement couplé au contenu de la collection à parcourir, ce qui signifie que le contenu de la collection correspondant à cet itérateur est le contenu actuel. Je ne veux absolument pas le faire dans mon cas. tri à bulles. Quand , il y a encore des threads qui insèrent des données dans ma collection, n'est-ce pas ? Java utilise donc ce mécanisme de traitement simple pour empêcher la collection d'être modifiée pendant le parcours.
Quant à savoir pourquoi supprimer "1" est suffisant, la raison réside dans la méthode hasNext() de foreach et de l'itérateur. Le sucre syntaxique de foreach est en fait
.
while(itr.hasNext()){
itr.next()
}
Donc, chaque boucle exécutera hasNext() en premier, alors jetez un œil à la façon dont hasNext() d'ArrayList est écrit :
public boolean hasNext() {
return cursor != size;
}
cursor est une variable utilisée pour marquer la position de l'itérateur. La variable commence à 0 et effectue une opération +1 à chaque fois que next est appelé, donc : Après que votre code supprime "1", size=1, curseur = 1, à ce moment hasNext() renvoie false et termine la boucle, donc votre itérateur n'appelle pas next pour trouver le deuxième élément, donc il n'y a aucun moyen de détecter modCount, donc il n'y aura pas d'exception de modification multi-thread mais lorsque vous avez supprimé "2", l'itérateur a appelé next deux fois, à ce moment-là, size=1, curseur=2 et hasNext() a renvoyé true, donc l'itérateur a bêtement appelé next() à nouveau, ce qui a également déclenché If. modCount n'est pas égal, une exception de modification multithread sera levée.
Lorsque votre ensemble comporte trois éléments, vous constaterez comme par magie que la suppression de "1" lèvera une exception, mais la suppression de "2" ne posera pas de problème. La raison est liée à l'exécution du programme ci-dessus. L'ordre est cohérent. .
Étant donné que le nombre dans la collection change lorsque vous ajoutez ou supprimez des éléments, des problèmes peuvent survenir lors du parcours. Par exemple, si une collection contient 10 éléments, elle doit être parcourue 10 fois. le nombre de traversées est incorrect, donc une erreur sera signalée
La description jaune dans le document est très intéressante.
Le résultat de l'exécution de cet exemple dépassera les attentes de tout le monde. Essayez donc de remplacer « 1 » par « 2 », cela aura-t-il le même résultat ?
Vous devez quand même regarder le code source de ArrayList pour cela, vous le saurez d'un coup d'œil.
ArrayList n'est pas thread-safe, ce qui signifie que vous modifiez la liste pendant le parcours. ArrayList lèvera une exception de modification simultanée dans ce cas.
La source de l'erreur
checkForComodification()
peut être connue grâce à l'erreur signalée. Si vous souhaitez éviter les erreurs, vous devez conservermodCount != expectedModCount
commefalse
.list.remove(Object)
appellera la méthodefastRemove(int)
, et elle modifiera inévitablementmodCount
à ce moment-là, et une erreur se produira à ce moment-là.Iterator<String> iterator = list.iterator()
; L'implémentation de cette méthode consiste à renvoyer une classe interneItr
(cette classe est utilisée dans le processus d'itération), mais la raison pour laquelle celaiterator.remove()
ne provoque pas d'erreurs est due à la relation entre cette méthode et L'implémentation consiste à vérifierArrayList.this.remove
avant de faire lecheckForComodfication
réel et à faireremove
aprèsexpectedModCount = modCount
afin qu'aucune erreur ne se produise.Itr.remove
Mise en œuvreS'il y a quelque chose qui ne va pas, veuillez le signaler @ChaCha哥 @puliuyinyi
Dans le cas d'un seul thread, lors de la suppression d'éléments lors du parcours de la liste, vous devez utiliser la méthode Remove d'Iterator au lieu de la méthode Remove de List, sinon une ConcurrentModificationException se produira. Imaginez simplement si un enseignant compte le nombre d'élèves dans toute la classe, et si les élèves ne respectent pas les règles et ne sortent pas et n'entrent pas, l'enseignant ne pourra certainement pas les compter.
Dans le cas du multi-threading, référez-vous à un de mes blogs : http://xxgblog.com/2016/04/02...
Tout d'abord, cela implique des opérations multi-thread. Iterator ne prend pas en charge les opérations multi-thread. La classe List maintiendra une variable modCount en interne pour enregistrer le nombre de modifications
Exemple : code source ArrayList
Chaque fois qu'un Iterator est généré, l'Iterator enregistrera le modCount. Chaque fois que la méthode next() est appelée, l'enregistrement sera comparé au modCount de la classe externe List. S'il s'avère inégal, un. une exception d'édition multithread sera levée.
Pourquoi fais-tu ça ? Je crois comprendre que vous avez créé un itérateur étroitement couplé au contenu de la collection à parcourir, ce qui signifie que le contenu de la collection correspondant à cet itérateur est le contenu actuel. Je ne veux absolument pas le faire dans mon cas. tri à bulles. Quand , il y a encore des threads qui insèrent des données dans ma collection, n'est-ce pas ? Java utilise donc ce mécanisme de traitement simple pour empêcher la collection d'être modifiée pendant le parcours.
Quant à savoir pourquoi supprimer "1" est suffisant, la raison réside dans la méthode hasNext() de foreach et de l'itérateur. Le sucre syntaxique de foreach est en fait
.Donc, chaque boucle exécutera hasNext() en premier, alors jetez un œil à la façon dont hasNext() d'ArrayList est écrit :
cursor est une variable utilisée pour marquer la position de l'itérateur. La variable commence à 0 et effectue une opération +1 à chaque fois que next est appelé, donc :
Après que votre code supprime "1", size=1, curseur = 1, à ce moment hasNext() renvoie false et termine la boucle, donc votre itérateur n'appelle pas next pour trouver le deuxième élément, donc il n'y a aucun moyen de détecter modCount, donc il n'y aura pas d'exception de modification multi-thread
mais lorsque vous avez supprimé "2", l'itérateur a appelé next deux fois, à ce moment-là, size=1, curseur=2 et hasNext() a renvoyé true, donc l'itérateur a bêtement appelé next() à nouveau, ce qui a également déclenché If. modCount n'est pas égal, une exception de modification multithread sera levée.
Lorsque votre ensemble comporte trois éléments, vous constaterez comme par magie que la suppression de "1" lèvera une exception, mais la suppression de "2" ne posera pas de problème. La raison est liée à l'exécution du programme ci-dessus. L'ordre est cohérent. .
Étant donné que le nombre dans la collection change lorsque vous ajoutez ou supprimez des éléments, des problèmes peuvent survenir lors du parcours. Par exemple, si une collection contient 10 éléments, elle doit être parcourue 10 fois. le nombre de traversées est incorrect, donc une erreur sera signalée
Supprimez-les simplement dans l’ordre inverse. Quoi qu’il en soit, essayez de ne pas supprimer la liste. Vous pouvez ajouter une balise de suppression
La description jaune dans le document est très intéressante.
Vous devez quand même regarder le code source de
ArrayList
pour cela, vous le saurez d'un coup d'œil.Supprimez-le simplement dans l'ordre inverse
ArrayList n'est pas thread-safe, ce qui signifie que vous modifiez la liste pendant le parcours.
ArrayList lèvera une exception de modification simultanée dans ce cas.