JDK10 ArrayList add 扩容怎么实现的(解析源码记录篇)?

JDK10 ArrayList add 扩容怎么实现的(解析源码记录篇)?

翻阅源码,初学源码,如有不对,请多指教

无参构造方法

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_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 = {};

无参构造方法 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
声明调用DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

带参构造方法

/**
 * 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);
    }
}
/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

带参构造方法
参数
initialCapacity - 列表的初始容量

/**
 * Constructs a list containing the elements of the specified
 * collection, in the order they are returned by the collection's
 * iterator.
 *
 * @param c the collection whose elements are to be placed into this list
 * @throws NullPointerException if the specified collection is null
 */
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // defend against c.toArray (incorrectly) not returning Object[]
        // (see e.g. https://bugs.openjdk.java.net/browse/JDK-6260652)
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

重点来了 add

添加当单个元素使用的方法为 public boolean add(E e)

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return {@code true} (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}
/**
 * This helper method split out from add(E) to keep method
 * bytecode size under 35 (the -XX:MaxInlineSize default value),
 * which helps when add(E) is called in a C1-compiled loop.
 */
private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}

进行数组赋值时,先会去修改数组的长度

private Object[] grow() {
    return grow(size + 1);
}
/**
 * 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
 * @throws OutOfMemoryError if minCapacity is less than zero
 */
private Object[] grow(int minCapacity) {
     // 进行拷贝数组
    // newCapacity(minCapacity) 拷贝的新数组的长度
    // 使用copyOf截取原数组,并返回带新长度的数组
    return elementData = Arrays.copyOf(elementData,newCapacity(minCapacity));
}

Arrays.copyOf 源码

源码原始注释英文翻译 复制指定的数组、截断或使用空值填充(如有需要) 所以拷贝有指定的长度。对于所有的指标
在原始数组和副本中都有效,这两个数组将 包含相同的值。中的任何有效的索引 复制但不是原始的,复制将包含{@code null}。
当且仅当指定长度时,这些索引才存在 大于原始数组的值。 生成的数组与原始数组的类完全相同。

 /**
     * Copies the specified array, truncating or padding with nulls (if necessary)
     * so the copy has the specified length.  For all indices that are
     * valid in both the original array and the copy, the two arrays will
     * contain identical values.  For any indices that are valid in the
     * copy but not the original, the copy will contain {@code null}.
     * Such indices will exist if and only if the specified length
     * is greater than that of the original array.
     * The resulting array is of exactly the same class as the original array.
     *
     * @param <T> the class of the objects in the array
     * @param original the array to be copied
     * @param newLength the length of the copy to be returned
     * @return a copy of the original array, truncated or padded with nulls
     *     to obtain the specified length
     * @throws NegativeArraySizeException if {@code newLength} is negative
     * @throws NullPointerException if {@code original} is null
     * @since 1.6
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
/**
 * Returns a capacity at least as large as the given minimum capacity.
 * Returns the current capacity increased by 50% if that suffices.
 * Will not return a capacity greater than MAX_ARRAY_SIZE unless
 * the given minimum capacity is greater than MAX_ARRAY_SIZE.
 *
 * @param minCapacity the desired minimum capacity
 * @throws OutOfMemoryError if minCapacity is less than zero
 */
 // 返回扩容新数组的长度 
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 声明一个新的变量 大小为 elementData.length 长度的 1.5 倍
    // oldCapacity >> 1 oldCapacity 右移一位,其效果相当于oldCapacity /2
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 判断新的扩容长度是否超过,
    if (newCapacity - minCapacity <= 0) {
        // elementData 存储ArrayList元素的数组缓冲区
        // DEFAULTCAPACITY_EMPTY_ELEMENTDATA 用于默认大小的空实例的共享空数组实例

        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // 返回 DEFAULT_CAPACITY  minCapacity 其中的最大值
            // DEFAULT_CAPACITY 默认10
            return Math.max(DEFAULT_CAPACITY, minCapacity);
            // 传入的长度小于0时,抛出异常
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        // 返回 原容量+新增的元素的个数
        return minCapacity;
    }
    
    // MAX_ARRAY_SIZE 要分配的数组的最大大小(除非必要)
    // 判断 newCapacity 扩容的新的数组长度是否 超过最大范围
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
}
private static int hugeCapacity(int minCapacity) {
    // 判断 minCapacity  为负数 抛出异常OutOfMemoryError
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
        // minCapacity 
        //MAX_ARRAY_SIZE 要分配的数组的最大大小(除非必要)
        //如果要分配的大小超过MAX_ARRAY_SIZE 就使用Integer的最大大小
    return (minCapacity > MAX_ARRAY_SIZE)
        ? Integer.MAX_VALUE
        : MAX_ARRAY_SIZE;
}
/**
 * The maximum size of array to allocate (unless necessary).
 * Some VMs reserve some header words in an array.
 * Attempts to allocate larger arrays may result in
 * OutOfMemoryError: Requested array size exceeds VM limit
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

整理总结:

每次ArrayList扩容,默认自动扩容多大
分为多种情况

1、 return Math.max(DEFAULT_CAPACITY, minCapacity);
DEFAULT_CAPACITY(值是10),说明:如果通过new ArrayList()来生成,第一次扩容默认采用

2、return (newCapacity - MAX_ARRAY_SIZE <= 0)? newCapacity : hugeCapacity(minCapacity);
原容量的一半:oldCapacity + (oldCapacity >>1),说明:默认扩容的容量是原容量的一半newCapacity,条件是newCapacity比minCapacity大且小于最大容量的定

3、return minCapacity; // 返回 原容量+新增的元素的个数
原容量+新增的元素的个数,说明:默认扩容的容量是原容量的一半newCapacity,但是如果newCapacity比minCapacity小,再扩容的大小为minCapacity

4、 return (minCapacity > MAX_ARRAY_SIZE)?Integer.MAX_VALUE : MAX_ARRAY_SIZE;
Integer.MAX_VALUE,说明:minCapacity> Integer.MAX_VALUE - 8,则扩容的大小是Integer.MAX_VALUE

5、MAX_ARRAY_SIZE Integer.MAX_VALUE - 8

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值