ArrayList扩容机制

    • 扩容步骤

  1. 扩容:把原来的数组复制到另一个内存空间更大的数组中。

  1. 添加元素:把新元素添加到扩容以后的数组中。

2、源码分析

2.1 ArrayList里面的属性

    /**
     * 默认初始化容量.
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * Shared empty array instance used for empty instances.
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * Shared empty array instance used for default sized empty instances. We
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
     * first element is added.
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * ArrayList的大小 (它包含的元素个数).
     *
     * @serial
     */
    private int size;

2.2 构造方法

分析之前我们先看一下ArrayList的两个构造方法

  • ArrayList():在用无参构造来创建对象的时候其实就是创建了一个空数组,长度为0。

  • ArrayList(int initialCapacity):传入的参数是正整数就按照传入的参数来确定创建数组的大小,否则异常。

    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    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);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

2.3 扩容

add方法就两步,

  1. 第一步:增加长度。

  1. 第二步:添加元素到数组,第二步就是将数据放到新数组最后一位。

第二步没什么好讲的,下面主要讲第一步。

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return true (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        // 增加长度
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 添加元素
        elementData[size++] = e;
        return true;
    }

我们看看ensureCapacityInternal(int minCapacity)这个增加长度的方法

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

这个地方我们看到了,如果在添加的时候远数组是空的,就直接给一个10的长度,否则的话就是size+1。

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

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

通过这个地方是真正的增加长度,当需要的长度大于原来数组长度的时候就需要扩容了,相反的则不需要扩容。

/**
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *
 * @param minCapacity the desired minimum capacity
 */
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);
}

扩容实现:

  • int newCapacity = oldCapacity + (oldCapacity >> 1);表示新容量=旧容量+0.5*旧容量=1.5倍旧容量。

  • elementData = Arrays.copyOf(elementData, newCapacity);将旧数组数据复制到新数组。

扩容结束。

你可能感兴趣的:(java,java,运维,数据结构)