HashMap和Hashtable的fail-fast机制

如果需要在迭代过程中修改删除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.csdn.net/tony521125/article/details/83965226

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值