arraylist扩容机制要怎么实现?arraylist怎么扩容

TheDisguiser 2020-06-01 21:09:05 java常见问答 11340

ArrayList大家都知道了吧,这是一个动态数组。以java语言来说,数组是定长的,在被创建之后就不能被加长或缩短了,因此,了解它的扩容机制对使用它尤为重要。下面,我们就一起来看看它的扩容机制是怎么实现的吧。

首先我们知道,ArrayList有着三种初始化方式:

1)指定大小初始化

public ArrayList(int initialCapacity)

2)传入一个Collection对象初始化,并将对象中的数据添加到ArrayList中

public ArrayList(Collection c)

3)默认构造函数初始化

public ArrayList()

ArrayList扩容机制发生在add()方法调用的时候,从下面的代码我们可以看出当使用无参构造函数创建ArrayList时,它的默认长度会为0

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList()
{
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

下面是add()方法的源码:

public boolean add(E e)
{
    //扩容
    ensureCapacityInternal(size + 1); // Increments modCount!!
    elementData[size++] = e;
    return true;
}

根据以上我们可以看到,ensureCapacityInternal()是用来扩容的,形参为最小扩容量,进入此方法后:

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

通过方法calculateCapacity(elementData, minCapacity)来获取:

private static int calculateCapacity(Object[] elementData, int minCapacity)
{
    //如果传入的是个空数组则最小容量取默认容量与minCapacity之间的最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
    {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
ensureExplicitCapacity方法可以判断是否需要扩容:
private void ensureExplicitCapacity(int minCapacity)
{
    modCount++;
    // 如果最小需要空间比elementData的内存空间要大,则需要扩容
    if (minCapacity - elementData.length > 0)
    //扩容 grow(minCapacity);
}

下面是重点来了,ArrayList扩容机制关键方法grow():

private void grow(int minCapacity)
{
    // 获取到ArrayList中elementData数组的内存空间长度
    int oldCapacity = elementData.length;
    // 扩容至原来的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,
    // 不够就将数组长度设置为需要的长度
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //若预设值大于默认的最大值检查是否溢出
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 调用Arrays.copyOf方法将elementData数组指向新的内存空间时newCapacity的连续空间
    // 并将elementData的数据复制到新的内存空间
    elementData = Arrays.copyOf(elementData, newCapacity);
}

因此,我们可以清晰看出ArrayList扩容的本质其实就是计算出新的扩容数组的size后实例化它,并将原有数组内容复制到新数组中去。

以上就是关于ArrayList扩容机制的全部内容了,如果你还想要了解更多有关ArrayList相关的java常见问答知识,就快来关注我们的网站吧。

推荐阅读:

arraylist类具体有什么概念?常用方法有哪些?

arraylist和linklist区别分别有哪些?

arraylist和vector的区别是什么?主要区别有哪些?java