Es gibt viele Möglichkeiten, Elemente in einer Liste oder Karte zu durchlaufen und zu löschen, und bei unsachgemäßer Verwendung treten Probleme auf. Lassen Sie uns in diesem Artikel mehr erfahren.
1. Elemente während des Listendurchlaufs löschen
Index-Indexdurchlauf verwenden
Beispiel: Löschen Sie 2 in der 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()); }
Ausgabeergebnis:
1 2 3 4 list=[1, 2, 3, 4]
Problem:
Das Ergebnis zeigt, dass nur eine 2 gelöscht wurde und die anderen 2 weggelassen wurden, warum Ja: Nach dem Löschen der ersten 2 wird die Anzahl der Elemente im Satz um 1 reduziert und die nachfolgenden Elemente werden um 1 nach vorne verschoben, wodurch die zweiten 2 weggelassen werden.
Für Schleifendurchquerung
Beispiel:
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()); }
Ergebnis:
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)
Erklärung:
Beschreibung von ConcurrentModificationException in JDK:
öffentliche Klasse ConcurrentModificationException erweitert
RuntimeException Diese Ausnahme wird ausgelöst, wenn die Methode eine gleichzeitige Änderung des Objekts erkennt, eine solche Änderung jedoch nicht zulässt.
Wenn beispielsweise ein Thread eine Sammlung durchläuft, ist es einem anderen Thread normalerweise nicht gestattet, die Sammlung linear zu ändern. In diesen Fällen sind die Ergebnisse der Iteration häufig unbestimmt. Einige Iteratorimplementierungen (einschließlich aller von der JRE bereitgestellten generischen Sammlungsimplementierungen) lösen diese Ausnahme möglicherweise aus, wenn dieses Verhalten erkannt wird. Iteratoren, die diesen Vorgang ausführen, werden als Fail-Fast-Iteratoren bezeichnet, da der Iterator völlig schnell ausfällt, ohne dass das Risiko eines willkürlichen, nicht spezifizierten Verhaltens zu einem späteren Zeitpunkt besteht.
Hinweis: Diese Ausnahme zeigt nicht immer an, dass das Objekt gleichzeitig von verschiedenen Threads geändert wurde. Ein Objekt kann diese Ausnahme auslösen, wenn ein einzelner Thread eine Folge von Methodenaufrufen ausgibt, die gegen den Vertrag des Objekts verstoßen. Wenn beispielsweise ein Thread eine Sammlung direkt ändert, während er mit einem Fail-Fast-Iterator darüber iteriert, löst der Iterator diese Ausnahme aus.
Hinweis: Das Fail-Fast-Verhalten von Iteratoren kann nicht garantiert werden, da es im Allgemeinen nicht möglich ist, feste Garantien dafür zu geben, ob unsynchronisierte gleichzeitige Änderungen auftreten. Fail-Fast-Vorgänge lösen auf Best-Effort-Basis eine ConcurrentModificationException aus. Daher ist es ein Fehler, ein Programm zu schreiben, das auf dieser Ausnahme basiert, um die Korrektheit solcher Vorgänge zu verbessern. Der richtige Ansatz ist: ConcurrentModificationException sollte nur zum Erkennen von Fehlern verwendet werden.
Für jeden in Java wird tatsächlich ein Iterator zur Verarbeitung verwendet. Der Iterator lässt nicht zu, dass die Sammlung während der Verwendung des Iterators gelöscht wird. Dies führte dazu, dass der Iterator eine ConcurrentModificationException auslöste.
Richtiger Weg
Beispiel:
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()); }
🎜>
2. Elemente während der Kartendurchquerung löschen Beispiel für die richtige Vorgehensweise:1 2 2 3 4 list=[1, 3, 4]
Ergebnis:
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()); } }
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
Beschreibung der Methode „remove()“ in der JDK-API:
void remove() entfernt das letzte vom Iterator zurückgegebene Element aus der Sammlung, auf die der Iterator zeigt (optionale Aktion). Diese Methode kann nur einmal pro Aufruf von next aufgerufen werden. Das Verhalten eines Iterators ist undefiniert, wenn die Sammlung, auf die der Iterator zeigt, während der Iteration auf andere Weise als durch den Aufruf dieser Methode geändert wird.
Wirft aus: UnsupportedOperationException – wenn der Iterator den Entfernungsvorgang nicht unterstützt. IllegalStateException – wenn die nächste Methode nicht aufgerufen wurde oder die Remove-Methode seit dem letzten Aufruf der nächsten Methode aufgerufen wurde.
Zusammenfassung
Weitere Artikel zum Löschen von Elementen während der Listen- oder Kartendurchquerung in Java finden Sie auf der chinesischen PHP-Website!