ArrayList源码阅读

ArrayList源码阅读笔记

内部属性
    //默认容量
    private static final int DEFAULT_CAPACITY = 10;
    //对于已知大小为0 的 返回此空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //默认容量DEFAULT_CAPACITY的空数组 , 暂时实际为0 的空数组 ,初次执行add方法时,会扩容为DEFAULT_CAPACITY
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //存放数据的数组的缓存变量,不可序列化
    transient Object[] elementData;
    //元素数量
    private int size;
    //父级AbstractList的成员属性:用于记录集合结构变化次数(扩容、删除、新增等所有会改变集合长度的操作)
    protected transient int modCount = 0;
构造方法
1、public ArrayList(int initialCapacity) :
	根据给定大小,初始化elementData  ;
	如果大小为0 ,设置 elementData =  EMPTY_ELEMENTDATA 空数组
2、public ArrayList() :
	设置 elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组,
	初次执行add()时会被扩容为默认大小
3、public ArrayList(Collection<? extends E> c) :
	c不能为null,c长度为0 ,设置elementData = EMPTY_ELEMENTDATA 空数组 ,
	否则elementData 长度为c的大小
增删改查
add : 新增
    1、如果是指定索引新增:检查索引 rangeCheckForAdd(int index) 
    2、判断是否需要扩容 (当前集合元素个数+1,作为最小参数)
    3、添加元素
set : 修改
    1、检查索引 rangeCheck(index);
    2、修改
remove: 删除
    1、根据索引删除 : 检查索引 rangeCheck(index);
    2、删除
get : 查看
    1、检查索引 rangeCheck(index);
    2、返回元素
扩容机制
1、根据当前集合实际元素siez + 1 作为集合需要的最小容量值,判断是否需要扩容 【应为只有add 才会有扩容,所以需要用size+1判断本次新增是否需要扩容】
2、 ensureCapacityInternal:确定内部需要容量最小值 
    private void ensureCapacityInternal(int minCapacity) {
        //初次执行add 无参构造容量设置为默认容量
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }
3、:ensureExplicitCapacity-确保容量
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;
        //所需最小容量 大于 当前elementData长度 执行扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
4、执行扩容:
    private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        // 扩容 1.5倍  
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)  //扩容1.5倍后,新容量 小于 所需最小容量 ,使用最小容量为扩容后大小 
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0) //扩容1.5倍后,新容量超过数组支持的最大容量值,使用最大值
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);//拷贝数据到一个新的容量大小的数组中
    }

遍历

foreach 使用了modCount结构变化次数验证,遍历过程中改变size操作会报ConcurrentModificationException

    public void forEach(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        final int expectedModCount = modCount;
        @SuppressWarnings("unchecked")
        final E[] elementData = (E[]) this.elementData;
        final int size = this.size;
        for (int i=0; modCount == expectedModCount && i < size; i++) {
            action.accept(elementData[i]);
        }
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }

Iterator:内部类Itr迭代器 remove方法显示的设置modCount跟操作后相等,所以支持迭代过程中修改

private class Itr implements Iterator<E> {
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                ArrayList.this.remove(lastRet);
                cursor = lastRet;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
}
序列化 序列化后的流中记录了集合结构变化次数,所以读操作后在修改,也会发现

读 :readObject

    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

写 :writeObject

    private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // Write out element count, and any hidden stuff
        int expectedModCount = modCount;
        s.defaultWriteObject();

        // Write out size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // Write out all elements in the proper正确的 order.
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        //写的过程中,集合结构被改变,会报错
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值