HashMap遍历时删除元素的有哪些实现方法?

首先结论如下: 第1种方法 - for-each遍历HashMap.entrySet,使用HashMap.remove()删除(结果:抛出异常)。 第2种方法-for-each遍历HashMap.keySet,使用HashMap.remove()删除(结果:抛出异常)。 第3种方法-使用HashMap.entrySet().iterator()遍历删除(结果:正确删除)。 下面让我们来详细探究一下原因吧! HashMap的遍历删除方法与ArrayList的大同小异,只是api的调用方式不同。首先初始化一个HashMap,我们要删除key包含"3"字符串的键值对。 ```java HashMap<String,Integer> hashMap = new HashMap<String,Integer>(); hashMap.put("key1",1); hashMap.put("key2",2); hashMap.put("key3",3); hashMap.put("key4",4); hashMap.put("key5",5); hashMap.put("key6",6); ``` 第1种方法 - for-each遍历HashMap.entrySet,使用HashMap.remove()删除(结果:抛出异常) ```java for (Map.Entry<String,Integer> entry: hashMap.entrySet()) { String key = entry.getKey(); if(key.contains("3")){ hashMap.remove(entry.getKey()); } System.out.println("当前HashMap是"+hashMap+" 当前entry是"+entry); } ``` 输出结果: ```java 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前entry是key1=1 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前entry是key2=2 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前entry是key5=5 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前entry是key6=6 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4} 当前entry是key3=3 Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429) at java.util.HashMap$EntryIterator.next(HashMap.java:1463) at java.util.HashMap$EntryIterator.next(HashMap.java:1461) at com.test.HashMapTest.removeWayOne(HashMapTest.java:29) at com.test.HashMapTest.main(HashMapTest.java:22) ``` 第2种方法-for-each遍历HashMap.keySet,使用HashMap.remove()删除(结果:抛出异常) ```java Set<String> keySet = hashMap.keySet(); for(String key : keySet){ if(key.contains("3")){ keySet.remove(key); } System.out.println("当前HashMap是"+hashMap+" 当前key是"+key); } ``` 输出结果如下: ```java 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前key是key1 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前key是key2 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前key是key5 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key3=3, key4=4} 当前key是key6 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4} 当前key是key3 Exception in thread "main" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextNode(HashMap.java:1429) at java.util.HashMap$KeyIterator.next(HashMap.java:1453) at com.test.HashMapTest.removeWayTwo(HashMapTest.java:40) at com.test.HashMapTest.main(HashMapTest.java:23) ``` 第3种方法-使用HashMap.entrySet().iterator()遍历删除(结果:正确删除) ```java Iterator<Map.Entry<String, Integer>> iterator = hashMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> entry = iterator.next(); if(entry.getKey().contains("3")){ iterator.remove(); } System.out.println("当前HashMap是"+hashMap+" 当前entry是"+entry); } ``` 输出结果: ```java 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4, deletekey=3} 当前entry是key1=1 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4, deletekey=3} 当前entry是key2=2 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4, deletekey=3} 当前entry是key5=5 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4, deletekey=3} 当前entry是key6=6 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4, deletekey=3} 当前entry是key4=4 当前HashMap是{key1=1, key2=2, key5=5, key6=6, key4=4} 当前entry是deletekey=3 ``` 第1种方法和第2种方法抛出ConcurrentModificationException异常与上面ArrayList错误遍历-删除方法的原因一致,HashIterator也有一个expectedModCount,在遍历时获取下一个元素时,会调用next()方法,然后对 expectedModCount和modCount进行判断,不一致就抛出ConcurrentModificationException异常。 ```java abstract class HashIterator { Node<K,V> next; // next entry to return Node<K,V> current; // current entry int expectedModCount; // for fast-fail int index; // current slot HashIterator() { expectedModCount = modCount; Node<K,V>[] t = table; current = next = null; index = 0; if (t != null && size > 0) { // advance to first entry do {} while (index < t.length && (next = t[index++]) == null); } } public final boolean hasNext() { return next != null; } final Node<K,V> nextNode() { Node<K,V>[] t; Node<K,V> e = next; if (modCount != expectedModCount) throw new ConcurrentModificationException(); if (e == null) throw new NoSuchElementException(); if ((next = (current = e).next) == null && (t = table) != null) { do {} while (index < t.length && (next = t[index++]) == null); } return e; } public final void remove() { Node<K,V> p = current; if (p == null) throw new IllegalStateException(); if (modCount != expectedModCount) throw new ConcurrentModificationException(); current = null; K key = p.key; removeNode(hash(key), key, null, false, false); expectedModCount = modCount; } } ```