Je compare toutes les entrées d'un HashMap
à toutes les autres entrées du même HashMap
. Lors de l'itération du HashMap
, je supprime certains éléments en fonction de certaines conditions. Cependant, je continue à recevoir l 'ConcurrentModificationException
.
Iterator<Entry<String, String>> i = map.entrySet().iterator(); while (i.hasNext()) { Entry<String, String> next = i.next(); for (Entry<String,String> e : map.entrySet()) { if (e.getKey() != next.getKey()){ String[] positions_e = fields_e[1].split("-"); int start_e = Integer.parseInt(positions_e[0]); int end_e = Integer.parseInt(positions_e[1]); String[] positions_next = fields_next[1].split("-"); int start_next = Integer.parseInt(positions_next[0]); int end_next = Integer.parseInt(positions_next[1]); if (start_e <= start_next || end_e <= end_next )) { i.remove(); } } }
4 Réponses :
Vous supprimez des éléments de la collection via l'itérateur i
tout en l'itérant avec un itérateur différent, celui implicite utilisé par votre boucle foreach.
Vous allez toujours avoir ce problème si vous avez des itérations imbriquées sur la même collection et essayez de supprimer des éléments de la boucle interne. L'utilisation de l'itérateur interne ou externe pour supprimer l'élément de la collection produit une ConcurrentModificationException
à partir de l'autre itérateur.
Puisque vous utilisez i
pour supprimer l'élément, la meilleure stratégie ici est probablement de sortir
de la boucle interne après avoir appelé remove code >.
Utilisez iterator ou lambda avec removeIf pour la deuxième boucle.
pour (Entry
)
Itérateur pour la carte: https: //www.techiedelight. com / iterate-map-in-java-using-entryset /
Lambda pour la carte: https://javarevisited.blogspot.com/2017/08/how-to-remove-key-value-pairs-from-hashmap-java8-example.html#axzz5eHbDQxwp p>
Voici une méthode qui n'implique pas de deuxième carte ou liste et augmente également la lisibilité de votre code:
Extrayez votre condition dans une méthode spearate:
Map<String, String> filteredMap = map.entrySet().stream() .filter(entry -> myCondition(entry, map)) .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
Utilisez les flux java8 pour filtrer la carte en fonction de votre condition:
private boolean myCondition(Entry<String, String> currentEntry, Map<String, String> map) { for (Entry<String, String> entry : map.entrySet()) { ... if (...) { return true; } return false; } }
Pour la sécurité de votre code, java ne vous permet pas de supprimer les éléments qui appartiennent à votre structure de données pendant que vous l'itérez. Une façon de le faire est de: cloner votre hashmap, itérer dans la carte de copie et faire la comparaison dessus. si la condition indique qu'un élément doit être supprimé, essayez de le supprimer de votre carte de hachage d'origine.
Créez une nouvelle collection de clés à supprimer et au lieu de
i.remove ();
faitestoBeRemoved.add (i.getKey ());
. Puis en dehors de la boucle whiletoBeRemoved.forEach (t -> map.remove (t));
Il n'y a aucun moyen de faire cela dans le même hashmap. Créez une réplique de la carte de hachage existante, puis supprimez les éléments de la copie.
@ BorisPavlović J'utilise java 7
A moins que ce ne soit pas votre vrai code, notez que les positions, les calculs de début et de fin pourraient se faire avant la boucle ... Dans ce cas, tout le problème devient beaucoup plus simple.
@sart puis parcourez
toBeRemoved
dans une bouclefor
...Vous pourriez (ou devriez) avoir
break;
aprèsi.remove ();
. Je ne sais pas pourquoi vous laisseriez la boucle intérieure continuer dans ce cas@assylias Je ne sais pas comment le calcul de début et de fin pourrait être effectué avant la boucle car je voudrais faire ces calculs pour chaque entrée.
@sart mais vous n'utilisez pas
e
ounext
pour calculer ces valeurs ...@assylias vous avez raison
@ernest_k cela a fonctionné quand j'ai utilisé la pause; Je vous remercie!
Alors, après avoir confirmé ce que @assylias a dit, quelle est la question? L'insertion d'un
break
transforme effectivement la boucle interne en code un bloc exécuté une seule fois, ce qui est possible car le bloc de code interne ne dépend pas de la variable de boucle, mais en fait, il n'en a même pas besoin la boucle extérieure. Vous n'avez besoin d'effectuer ce calcul qu'une seule fois, car son résultat ne change jamais, et sitrue
, appelezclear ()
sur lacarte
. Mais vous devriez vraiment réfléchir à la manière dont vous êtes arrivé à la solution à double boucle pour évaluer une condition immuable. Il semble y avoir une énorme erreur de logique dans votre application.Est-ce que cela répond à votre question? Itérer dans une collection, en évitant ConcurrentModificationException lors de la suppression d'objets dans une boucle a >