集合为什么不能在遍历的同时删除其中的元素?

问题:删除Set中的某些元素的时候,使用边遍历,边删除的方法,报以下异常:ConcurrentModificationException

ConcurrentModificationException是Java集合的一个快速失败(fail-fast)机制,防止多个线程同时修改同一个集合的元素。

集合使用迭代器删除元素代码及原理:

private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;    // next entry to return
        int expectedModCount;    // For fast-fail
        int index;        // current slot
        Entry<K,V> current;    // current entry
 
        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }
 
        public final boolean hasNext() {
            return next != null;
        }
 
        final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();
 
            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        current = e;
            return e;
        }
//调用的这个方法
        public void remove() {
 
            if (current == null)
                throw new IllegalStateException();
//玄机就在这里:expectedModCount,拷贝网上找来的说明,
/** 
*在Iterator的内部有个expectedModCount 变量, 
*该变量每次初始化*Iterator的时候等于ArrayList的modCount,modCount记录了对ArrayList的结构修改次数, 
*在通过Iterator对ArrayList进行结构的修改的时候都会将expectedModCount 与modCount同步, 
*但是如果在通过Iterator访问的时候同时又通过索引的方式去修改ArrayList的结构的话, 
*由于通过索引的方式只会修改modCount不会同步修改expectedModCount 就会导致 
*modCount和expectedModCount 不相等就会抛ConcurrentModificationException, 
*这也就是Iterator的fail-fast,快速失效的。所以只要采取一种方式操作ArrayList就不会出问题, 
*当然ArrayList不是线程安全的,此处不讨论对线程问题。 
 
* http://sushe1424.iteye.com/blog/1110796
*/  
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Object k = current.key;
            current = null;
            HashMap.this.removeEntryForKey(k);
            expectedModCount = modCount;
        }
 
    }

java中对remove方法的介绍:
remove
void remove()从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
每次调用 next 只能调用一次此方法。如果进行迭代时用调用此方法之外的其他方式修改了该
迭代器所指向的 collection,则迭代器的行为是不确定的。

参考:
https://blog.csdn.net/yin_jw/article/details/39668673
https://bbs.csdn.net/topics/390711013
http://sushe1424.iteye.com/blog/1110796

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值