ArrayList中modCount的作用

  • 这个成员变量记录着集合的修改次数,即每次add或者remove他的值都会加1.

Iterator的源码:

public Iterator<E> iterator(){
    return new Itr();
}

返回的是一个Itr对象,这个Itr是ArrayList的内部类

private class Itr implements Iterator<E> {
    int cursor;       // index of next element to return   //下一个元素的游标
    int lastRet = -1; // index of last element returned; -1 if no such  //上一个元素的
    int expectedModCount = modCount;  //修改计数器期望值
 
    public boolean hasNext() {
        return cursor != size;
    }
    @SuppressWarnings("unchecked")
    public E next() {
        checkForComodification();
        int i = cursor; //此时的游标,指向的是本次要遍历的对象,因为上一次已经++了,初始值为0,没有++的情况下是第一个元素
        if (i >= size)   //越界了
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i + 1;  //游标指向了下一个元素, 但 i 的值没有变
        return (E) elementData[lastRet = i];   //将 i 赋值给lastRet,取的值是方法开始时int i=cursor;中的cursor指向的值,而且最终这个游标的数值赋值给了lastRet
    }
    public void remove() {
        if (lastRet < 0)  // 如果没有next()操作就直接remove的话,lastRet=-1,会抛异常
            throw new IllegalStateException();
        checkForComodification();
        try {
            ArrayList.this.remove(lastRet); // remove之前,cursor、lastRet的值没有修改,都是上次next之后的值,因此此处的lastRet指向上次next获取的元素
            cursor = lastRet;
            lastRet = -1;
            expectedModCount = modCount;  // 手动将ArrayList.remove()后modCount的值赋给expectedModCount,避免引起不一致
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
    @Override
    @SuppressWarnings("unchecked")
    public void forEachRemaining(Consumer<? super E> consumer) {
        Objects.requireNonNull(consumer);
        final int size = ArrayList.this.size;
        int i = cursor;
        if (i >= size) {
            return;
        }
        final Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length) {
            throw new ConcurrentModificationException();
        }
        while (i != size && modCount == expectedModCount) {
            consumer.accept((E) elementData[i++]);
        }
        // update once at end of iteration to reduce heap write traffic
        cursor = i;
        lastRet = i - 1;
        checkForComodification();
    }
    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

主要关注三个点
  • 1、expectedModCount的初值为modCount

  • 2、hasNext的判断条件为cursor!=size,就是当前迭代的位置不是数组的最大容量值就返回true

  • 3、next和remove操作之前都会先调用checkForComodification来检查expectedModCount和modCount是否相等

如果没checkForComodification去检查expectedModCount与modCount相等,这个程序肯定会报ArrayIndexOutOfBoundsException

这样的异常显然不是应该出现的(这些运行时错误都是使用者的逻辑错误导致的,我们的JDK那么高端,不会出现使用错误,我们只抛出使用者造成的错误,而这个错误是设计者应该考虑的),为了避免出现这样的异常,定义了检查。所以抛出ConcurrentModificationException异常更能说明问题。

进行对修改的同步检查:
final void checkForComodification(){
    if(modCount != expectedModCount())
    throws new ConcurrentModificationException();
}
  • 现在其作用非常清楚,在对一个集合对象进行跌代操作的同时,并不限制对集合对象的元素进行操作,这些操作包括一些可能引起跌代错误的add()或remove()等危险操作。在AbstractList中,使用了一个简单的机制来规避这些风险。 这就是modCount和expectedModCount的作用所在
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值