坑死我的remove之ConcurrentModificationException

坑死我的remove之ConcurrentModificationException

先上段代码
    List<String> list = new ArrayList<>();
    Collections.addAll(list,"str1","str2","str3","str4","str5");
    list.forEach(str->{
        if("str1".equals(str))
        list.remove(str);
    });

本来想删除"str1",结果喜提ConcurrentModificationException
接下来就看看,我喜提ConcurrentModificationException的道路上,ArrayList作出了哪些努力与贡献
首先:

 public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);//判空
        final int expectedModCount = modCount;//预期计算=计数,modCount敲黑板,要考
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        //遍历的时候,判断了 modCount==expectedModCount
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();//举报,就是它。
        }
    }

这里我们已经看到ConcurrentModificationException了,但是,我是怎么走到这一步的呢?
上面if里面条件:当modCount != expectedModCount时,抛出异常,也就是说modCount发生了改变?!!!
那他是啥时候改变的,为啥改变了/fd,再往下走走看。我们顺利的拿到了第一个数据,并且返回了,那么
一定是remove搞得鬼咯。看看remove

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);//o!=null,执行fastRemove
                    return true;
                }
        }
        return false;
    }

纵观上面的代码,跟modCount没有关系!那真凶肯定是藏在fastRemove里了

 private void fastRemove(int index) {
        modCount++;//!!!!
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

modCount++啊啊啊,为什么要++,看看modCount作何解释

   /**
     * The number of times this list has been <i>structurally modified</i>.
     * Structural modifications are those that change the size of the
     * list, or otherwise perturb it in such a fashion that iterations in
     * progress may yield incorrect results.
     *
     * <p>This field is used by the iterator and list iterator implementation
     * returned by the {@code iterator} and {@code listIterator} methods.
     * If the value of this field changes unexpectedly, the iterator (or list
     * iterator) will throw a {@code ConcurrentModificationException} in
     * response to the {@code next}, {@code remove}, {@code previous},
     * {@code set} or {@code add} operations.  This provides
     * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
     * the face of concurrent modification during iteration.
     *
     * <p><b>Use of this field by subclasses is optional.</b> If a subclass
     * wishes to provide fail-fast iterators (and list iterators), then it
     * merely has to increment this field in its {@code add(int, E)} and
     * {@code remove(int)} methods (and any other methods that it overrides
     * that result in structural modifications to the list).  A single call to
     * {@code add(int, E)} or {@code remove(int)} must add no more than
     * one to this field, or the iterators (and list iterators) will throw
     * bogus {@code ConcurrentModificationExceptions}.  If an implementation
     * does not wish to provide fail-fast iterators, this field may be
     * ignored.
     */

@_@The number of times this list has been structurally modified(以下来自谷歌翻译:此列表已被结构修改的次数)
成功破案,真相只有一个:当list发生结构的更改时,modCount都+1,以防止正在进行中的迭代产生不正确的结果。

正确的remove方法, 应该使用迭代器里面的 remove 方法

 Iterator<Integer> iterator = integers.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            if (Integer.valueOf(1).equals(next)) {
                iterator.remove();
            }
            if (Integer.valueOf(2).equals(next)) {
                iterator.remove();
            }
        }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值