如果需要在迭代过程中修改删除HashMap或者Hashtable中的数据,需要使用Iterator迭代器,Hashtable中也可以使用Enumeraction来迭代。
HashMap正常迭代代码:
@Test
public void testHashMapIterator() throws Exception {
Map<String,String> hashMap = new HashMap<String,String>();
hashMap.put("key1","value1");
hashMap.put("key2","value2");
hashMap.put("key3","value3");
hashMap.put("key4","value4");
Iterator<Entry<String, String>> it = hashMap.entrySet().iterator();
while(it.hasNext()) {
System.out.println(it.next());
it.remove();
//hashMap.remove("key1");
}
}
会抛出ConcurrentModificationException的修改方式(不限于下面这种,使用forEach语句也是会报错的,forEach底层依然是简单的for循环)
//java.util.ConcurrentModificationException
@Test
public void testHashMapIteratorException() throws Exception {
Map<String,String> hashMap = new HashMap<String,String>();
hashMap.put("key1","value1");
hashMap.put("key2","value2");
hashMap.put("key3","value3");
hashMap.put("key4","value4");
Iterator<Entry<String, String>> it = hashMap.entrySet().iterator();
while(it.hasNext()) {
System.out.println(it.next());
hashMap.remove("key1");
}
}
Hashtable的用Iterator正常迭代删除数据和错误迭代删除数据和HashMap都是一样的,下面说一下Hashtable中Enumeraction实现迭代的方式,这种方式在迭代的时候修改数据也是不会报异常的。
@Test
public void testHashtableEnumeration() throws Exception {
Hashtable<String,String> hashTable = new Hashtable<String,String>();
hashTable.put("key1","value1");
hashTable.put("key2","value2");
hashTable.put("key3","value3");
hashTable.put("key4","value4");
Enumeration<String> e = hashTable.elements();
while(e.hasMoreElements()) {
hashTable.remove("key1");
System.out.println(e.nextElement());
}
}
HashIteractor底层代码
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;
...//省略部分代码
}
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;
}
...//省略部分代码
}
对于modCount官方注释是The number of times this HashMap has been structurally modified,也就是这个变量是用来记录HashMap结构修改的次数
所以可以猜测当用Iterator实例的remove去修改集合中的元素,modCount的值是不会变化的,而直接用集合的remove方法修改集合中的元素modCount++,为什么这么做的原因目前还没理解,静待后面的学习。
去查了一下
参考:
https://blog.youkuaiyun.com/tony521125/article/details/83965226