ArrayList的add()方法扩容原理,源码分析

ArrayList里面有属性是用来存放元素的
transient Object[] elementData;


调用无惨构造方法时,把一个空数组给我elementData

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

DEFAULTCAPACITY_EMPTY_ELEMENTDATA是个空数组

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

有参构造方法
当传入大小大于0时,就把内部数组初始化为传入的大小
当传入大小等于0时,就把内部数组初始化为EMPTY_ELEMENTDATA(是一个空数组)
当是负数等时,报异常

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

添加元素add()

public boolean add(E e) {
    // 传入的是size +1,size是集合中元素的个数   
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    // 把元素添加到数组第size的位置(size是数组的数组中元素个数)再给size加1
    elementData[size++] = e;
    return true;
}

进入ensureCapacityInternal()

private void ensureCapacityInternal(int minCapacity) {
    // 先调用calculateCapacity(),再调用ensureExplicitCapacity()
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

查看calculateCapaccity(),传入装元素的数组和size+1(minCapacity)

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    // 如果现在数组的空的,返回DEFAULT_CAPACITY(是10)和minCapacity(size+1)的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    // 如果现在的数组不是空的,返回minCapacity(size+1)
    return minCapacity;
}

进入ensureExplicitCapacity()方法

private void ensureExplicitCapacity(int minCapacity) {
    // 将修改记录次数+1,该变量主要是用来实现fail-fast机制的
    modCount++;

    // overflow-conscious code
    //  判断是否需要扩容,若minCapacity比数组可容纳个数大,就要扩容  
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

再调用grow()

private void grow(int minCapacity) {
    // overflow-conscious code
    // 数组旧容量
    int oldCapacity = elementData.length;
    // newCapacity = 数组旧容量 + 数组旧容量>>1(偶数除以2,基数减1除以2)
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果newCapacity<minCapacity  , 就使用minCapacity,例如,第一次add就会这样
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    // 如果newCapacity >  MAX_ARRAY_SIZE(Integr的最大值减8 ,调用hugeCapacity()
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

最后调用Arrays.copyOf()对数组进行扩容


hugeCapacity()
如果minCapacity大于Integer最大值-8,就取Integer的最大值,要不然就取Integer最大值-8

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

ensureCapacityInternal()方法 传入的是size +1
如果是数组是空的, 就创建一个大小是10的数组(DEFAULT_CAPACITY是10)
如果数组不是空的就调用ensureExplicitCapacity()


总结

无参构造,初始容量是0
有参构造,会先初始化内部数组的大小
调用add(),如果是第一次添加,数组是空的,就数组的大小是10

若不是空的,就是zise+1,返回一个值minCapacity

newCapacity = 先把之前的数组的容量 + 之前的数组容量>>1(偶数除以1,基数减1除以2)    ---相当于1.5倍
再取minCapacity和newCapacity的最大值赋值给newCapacity

再调用grow()
newCapacity = 先把之前的数组的容量 + 之前的数组容量>>1(偶数除以1,基数减1除以2)
再取minCapacity和newCapacity的最大值赋值给newCapacity
若newCapacity > MAX_ARRAY_SIZE(Integr的最大值减8 ,调用hugeCapacity()
如果minCapacity大于Integer最大值-8,就取Integer的最大值,要不然就取Integer最大值-8

最后调用Arrays.copyOf()对数组进行扩容,生成的新的数组赋值给数组属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值