ArrayList的自动扩容机制

ArrayList的继承体系

ArrayList 是 java 集合框架中比较常用的数据结构。继承自 AbstractList,实现了 List 接口。基于数组实现容量大小动态变化。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArraList的扩容机制

首先看下ArrayList的Add方法:

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

其中ensureCapicityInternal()是添加元素时调用的扩容方法:

        如果使用默认的构造参数的话,则选择minCapacity和DEFAULT_CAPACITY中较大的一个来作为最小的初始容量,大家可能奇怪,既然判断了初始化这一说,为何还会有传入的minCapacity,
和DEFAULT_CAPACITY比较这一说,是因为ensureCapacityInternal也会被addAll调用

解释:当集合对象第一次添加元素的时候,集合大小扩容为10(若使用addAll方法添加元素,则初始化大小为10和添加集合长度的较大值)

private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);//非初始化状态时,判断集合是否需要扩容

    }

当集合初始化完毕后,再次添加元素时。调用其ensureExplicitCapacity方法:

解释:if (minCapacity - elementData.length > 0),如果最小需要空间比elementData的内存空间要大,扩容,调用核心方法grow()

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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

核心方法grow():

 解释: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);(若预设值大于默认的最大值检查是否溢出)

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        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);
    }

总结

  • 1.ArrayList创建对象时,若未指定集合大小初始化大小为0;若已指定大小,集合大小为指定的大小;
  • 2.当第一次调用add方法时,集合长度变为10和addAll内容之间的较大值;
  • 3.之后再调用add方法,先将集合扩大1.5倍,如果仍然不够,新长度为传入集合大小;
上一篇:ArrayList源码解析


下一篇:深入理解之源码剖析Vector