Il existe de nombreuses façons de parcourir et de supprimer des éléments dans une liste ou une carte, et des problèmes surviendront en cas d'utilisation incorrecte. Apprenons-en davantage à travers cet article.
1. Supprimer des éléments lors du parcours de la liste
Utiliser le parcours d'indice d'index
Exemple : supprimer 2 dans la liste
public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(2); list.add(3); list.add(4); for (int i = 0; i < list.size(); i++) { if(2 == list.get(i)){ list.remove(i); } System.out.println(list.get(i)); } System.out.println("list=" + list.toString()); }
Résultat de sortie :
1 2 3 4 list=[1, 2, 3, 4]
Problème :
Le résultat montre qu'un seul 2 a été supprimé et les 2 autres ont été omis, pourquoi Oui : après la suppression des 2 premiers, le nombre d'éléments de l'ensemble est réduit de 1 et les éléments suivants sont avancés de 1, entraînant l'omission des 2 seconds.
Pour le parcours de boucle
Exemple :
public static void listIterator2(){ List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(2); list.add(3); list.add(4); for (int value : list) { if(2 == value){ list.remove(value); } System.out.println(value); } System.out.println("list=" + list.toString()); }
Résultat :
Exception in thread "main" 1 2 java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(Unknown Source) at java.util.ArrayList$Itr.next(Unknown Source) at test.ListIterator.listIterator2(ListIterator.java:39) at test.ListIterator.main(ListIterator.java:10)
Explication :
Description de ConcurrentModificationException dans jdk :
classe publique ConcurrentModificationException extends
RuntimeException Cette exception est lancé lorsque la méthode détecte une modification simultanée de l'objet, mais n'autorise pas une telle modification.
Par exemple, lorsqu'un thread parcourt une collection, un autre thread n'est généralement pas autorisé à modifier linéairement la collection. Souvent, dans ces cas, le résultat de l’itération est indéterminé. Certaines implémentations d'itérateurs (y compris toutes les implémentations de collections génériques fournies par le JRE) peuvent choisir de lever cette exception si ce comportement est détecté. Les itérateurs qui effectuent cette opération sont appelés itérateurs à échec rapide, car l'itérateur échoue complètement rapidement sans risquer un comportement arbitraire non spécifié à un moment donné dans le futur.
Remarque : Cette exception n'indiquera pas toujours que l'objet a été modifié simultanément par différents threads. Un objet peut lever cette exception si un seul thread émet une séquence d'appels de méthode qui viole le contrat de l'objet. Par exemple, si un thread modifie directement une collection tout en la parcourant à l'aide d'un itérateur à échec rapide, l'itérateur lèvera cette exception.
Remarque : le comportement rapide des itérateurs n'est pas garanti car, en général, il n'est pas possible de garantir de manière concrète si des modifications simultanées non synchronisées se produiront. Les opérations rapides en cas d'échec génèrent une ConcurrentModificationException au mieux. Par conséquent, c'est une erreur d'écrire un programme qui s'appuie sur cette exception pour améliorer l'exactitude de telles opérations. L'approche correcte est la suivante : ConcurrentModificationException ne doit être utilisée que pour détecter les bogues.
Pour chacun, Java utilise en fait un itérateur pour le traitement. L'itérateur ne permet pas la suppression de la collection lors de l'utilisation de l'itérateur. Cela a donc amené l’itérateur à lancer ConcurrentModificationException.
Voie correcte
Exemple :
public static void listIterator3(){ List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(2); list.add(3); list.add(4); Iterator<Integer> it = list.iterator(); while (it.hasNext()){ Integer value = it.next(); if (2 == value) { it.remove(); } System.out.println(value); } System.out.println("list=" + list.toString()); }
Résultat :
1 2 2 3 4 list=[1, 3, 4]
2. Suppression d'éléments lors du parcours de la carte
Exemple d'approche correcte :
public static void main(String[] args) { HashMap<String, String> map = new HashMap<String, String>(); map.put("1", "test1"); map.put("2", "test2"); map.put("3", "test3"); map.put("4", "test4"); //完整遍历Map for (Entry<String, String> entry : map.entrySet()) { System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue()); } //删除元素 Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); while(it.hasNext()) { Map.Entry<String, String> entry= it.next(); String key= entry.getKey(); int k = Integer.parseInt(key); if(k%2==1) { System.out.printf("delete key:%s value:%s\r\n", key, entry.getValue()); it.remove(); } } //完整遍历Map for (Entry<String, String> entry : map.entrySet()) { System.out.printf("key: %s value:%s\r\n", entry.getKey(), entry.getValue()); } }
Résultat :
key: 1 value:test1 key: 2 value:test2 key: 3 value:test3 key: 4 value:test4 delete key:1 value:test1 delete key:3 value:test3 key: 2 value:test2 key: 4 value:test4
Remarque
Mais pour la méthode remove() de l'itérateur, il y a aussi des choses auxquelles nous devons prêter attention :
Chaque fois l'itérateur .next est appelée la méthode (), la méthode Remove() ne peut être appelée qu'une seule fois.
Avant d'appeler la méthode remove(), la méthode next() doit être appelée une fois.
Description de la méthode Remove() dans JDK-API :
void Remove() supprime le dernier élément renvoyé par l'itérateur de la collection pointée par l'itérateur (action facultative). Cette méthode ne peut être appelée qu'une seule fois par appel au suivant. Le comportement d'un itérateur n'est pas défini si la collection pointée par l'itérateur est modifiée alors qu'elle est itérée d'une manière autre qu'en appelant cette méthode.
Lance : UnsupportedOperationException - si l'itérateur ne prend pas en charge l'opération de suppression. IllegalStateException - si la méthode suivante n'a pas été appelée ou si la méthode Remove a été appelée depuis le dernier appel à la méthode suivante.
Résumé
Ce qui précède concerne la suppression d'éléments pendant le processus de parcours de List et Map. J'espère que le contenu de cet article pourra apporter de l'aide à l'étude ou au travail de chacun si vous en avez. questions Vous pouvez laisser des messages pour communiquer.
Pour plus d'articles sur la façon de supprimer des éléments lors du parcours d'une liste ou d'une carte en Java, veuillez faire attention au site Web PHP chinois !