Je ne comprends pas pourquoi je reçois une idée concurrenteModification lorsque je iTère via ce Le et utilisé comme ceci: p> multimap code>.
Je lis ce qui suit entrée , mais je ne suis pas sûr de bien comprendre le tout.
J'ai essayé d'ajouter un bloc synchronisé. Mais mon doute est de quoi se synchroniser et quand.
multimap code> est un champ et créé comme ceci: p>
for (Entry<GenericEvent, Command> entry : eventMultiMap.entries()) {
if (entry.getValue().equals(command)) {
eventMultiMap.remove(entry.getKey(), entry.getValue());
nbRemoved++;
}
}
5 Réponses :
appeler Supprimer sur une collection pendant que vous itération à travers cela entraînera une exception concurrente à chaque fois, même si tout est fait dans le même thread - la bonne chose à faire est d'obtenir un itérateur explicite et d'appeler () à ce sujet. .
Edit: Modification de votre exemple: P>
Iterator<Map.Entry<GenericEvent, Command>> i = eventMultiMap.entries().iterator(); while (i.hasNext()) { if (i.next().getValue().equals(command)) { i.remove(); nbRemoved++; } }
Ok, je reçois le point. Mais Itérateur
OK, l'itérateur sur les valeurs de la carte peut supprimer les valeurs. Merci. Je ne peux pas accepter votre réponse pour l'instant, Itérateur
Désolé. Ne pas avoir Google-collections au travail, je ne pouvais donc pas tester le code avant de la publier. S'ils sont conçus comme le Hashmap Java, il devrait être possible d'utiliser un itérateur sur les objets d'entrée - j'ai édité de la montrer et de le télécharger quand je rentre à la maison, si vous n'avez pas eu la chance de l'essayer en attendant.
Si un autre thread pourrait modifier votre multimap tandis que cette logique est en cours d'exécution, vous devez ajouter un bloc synchronisé au code de Mharris: ou, vous pouvez omettre l'itérateur comme suit, P> synchronized (eventMultimap) {
int oldSize = eventMultimap.size();
eventMultimap.values().removeAll(Collections.singleton(command));
nbRemoved = oldSize - eventMultimap.size();
}
J'aime le removeall (collection.Singleton (StufftToremove)). Merci.
Vous voudrez peut-être voir Ce blogpost pour Un autre piège produisant un ConcurrentModificationException code> lors de la traversée d'un multimap, sans autre fil d'interférence. En bref, si vous parcourez les touches de Multimap, accédez à la collection correspondante de valeurs associées à chaque clé et supprimez un élément d'une telle collection,
concurrentModificationException code> lorsque vous essayez d'accéder à la touche suivante - car la vidange d'une collection déclenche la suppression de la clé, modifiant ainsi structurellement le clavier de Multimap. P>
... Donc, le correctif pour cela serait de vérifier la taille de la valeur de la valeur pendant que vous l'itéritez, et si jamais cette valeur de valeur ne dispose que d'une entrée à gauche lorsque vous allez en retirer, il suffit de supprimer de l'itérateur du Keyset à la place.
Je préfère multimap.values (). Itérateur () code> Si vous ne vous souciez pas de la clé. Vous devriez également essayer de rester à l'écart de l'utilisation des blocs synchronisés autant que possible, car vous ne pouvez pas hiérarchiser efficacement.
Dans Java8, vous pouvez également utiliser une approche Lambda: p>
EventMultimap.entries (). Remudidif (généreuseCommandEntry -> GenericeventCommandentry.getvalue (). Equals (commande)); Code> P>
Voir aussi Stackoverflow.com/questions/1675037/...