Java ArrayList扩容机制

Java ArrayList扩容

上次我们说到ArrayList扩容机制较复杂,可以单独拿出来讲,这就补上。不附目录,因为适合一步一步理解(>_<)


一、add(E e):

我们先来看add(E e)方法

public boolean add(E e) {
        //重点在这里,我们来看ensureCapacityInternal()
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;// 末尾添加元素
        return true;
    }

二、ensureCapacityInternal()方法:

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

再分别来看calculateCapacity()和ensureExplicitCapacity()方法:


三、calculateCapacity():

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

这里有DEFAULTCAPACITY_EMPTY_ELEMENTDATA,我们再来看这是什么:

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};// 空数组

还有DEFAULT_CAPACITY:

private static final int DEFAULT_CAPACITY = 10;// 默认为10

现在我们就可以看懂calculateCapacity()了:

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {//判断是否为空
        return Math.max(DEFAULT_CAPACITY, minCapacity);// 如果为空,则默认返回10,对应我们初始化容量时的ArrayList
    }
    return minCapacity;//不为空,则返回传入的值minCapacity
}

所以在扩容时,如果我们是无参初始化的ArrayList,即容量为0,会先将容量赋为10


四、ensureExplicitCapacity()方法:

private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)// 判断是否超出界限
            grow(minCapacity);                   // 若超出,则调用grow()方法扩容
    }

可知grow()方法是整个扩容机制最重要的一步!


五、grow()方法扩容:

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;// 旧容量
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量是旧容量的1.5倍
    if (newCapacity - minCapacity < 0) // 新容量足够
        newCapacity = minCapacity;     
    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); //旧容量中存放的内容拷贝给新容量数组
}

我们拿出最关键的两行代码:

int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);

新的容量是旧容量的(oldCapacity + (oldCapacity >> 1))倍,这也就是我们常说的ArrayList扩容1.5倍


六、hugeCapacity()分支:

那么还有一条分支:

if (newCapacity - MAX_ARRAY_SIZE > 0)// 新的容量大于数组大小最大值
        newCapacity = hugeCapacity(minCapacity);

MAX_ARRAY_SIZE:

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

hugeCapacity():

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

所以不一定是原数组的1.5倍长度,也可能越界抛出异常,也可能返回长度Integer.MAX_VALUE或Integer.MAX_VALUE-8

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neko1145

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值