ArrayList数组扩容流程

本文详细介绍了Java中ArrayList的默认容量、最大容量及其扩容机制。当ArrayList容量不足时,会通过grow方法进行扩容,默认情况下扩容为原来的1.5倍。此外还介绍了如何通过Arrays.copyOf方法实现数据迁移。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList数组基础属性

  • DEFAULT_CAPACITY:默认容器大小,使用new创建ArrayList时不会初始化容器的容量
  • MAX_ARRAY_SIZE:Integer.MAX_VALUE - 8; 容器最大容量

代码流程

 public boolean add(E e) {
     modCount++; // 这个暂时没有研究
     add(e, elementData, size);
     return true;
}
private void add(E e, Object[] elementData, int s) {
	// 如果size和容器容量相等表示需要扩容 执行grow方法
    if (s == elementData.length)
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}
private Object[] grow() {
    return grow(size + 1);
}

private Object[] grow(int minCapacity) {
    return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity));
}

// 计算新的容器容量
private int newCapacity(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 新容器的容量约为 旧容器容量*1.5
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 此处在容器容量为0的时候执行代码(创建ArrayList时未指定长度)
    if (newCapacity - minCapacity <= 0) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return minCapacity;
    }
    
    return (newCapacity - MAX_ARRAY_SIZE <= 0)
        ? newCapacity
        : hugeCapacity(minCapacity);
Arrays.java
public static <T> T[] copyOf(T[] original, int newLength) {
    return (T[]) copyOf(original, newLength, original.getClass());
}
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    // 使用System.arraycopy方法将旧的数据拷贝至新的容器中
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
  • src - 源数组。
  • srcPos - 源数组中的起始位置。
  • dest - 目标数组。
  • destPos - 目的地数据中的起始位置。
  • length - 要复制的源数组元素的数量。
### Java ArrayList 扩容机制及实现原理 #### 1. 默认初始化与容量设置 在 Java 中,`ArrayList` 提供了两种主要的构造方式。一种是没有参数的构造函数,在这种情况下,`ArrayList` 的默认初始容量被设定为 `10`[^2]。另一种是可以指定初始容量的方式,允许开发者根据需求自定义数组的起始大小。 ```java public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } ``` 上述代码展示了无参构造器如何将 `elementData` 设置为一个特殊的空对象数组 `DEFAULTCAPACITY_EMPTY_ELEMENTDATA`,这表示尚未分配实际存储空间[^2]。 #### 2. 初始状态下的行为 当创建一个新的 `ArrayList` 并未显式添加任何元素时,它的内部实际上是一个空数组。直到第一次向其中添加元素时,才会触发扩容操作,并将其调整到至少能够容纳当前所需数量的元素,通常为 `10`[^3]。 #### 3. 扩容的核心逻辑 一旦现有的数组容量不足以满足新增加的元素,则会启动扩容流程。这一过程由私有方法 `grow(int minCapacity)` 负责处理: - **计算新的容量**:新数组的大小通常是原数组大小的约 `1.5 倍` (即 `(oldCapacity * 3)/2 + 1`)。 如果经过此运算得出的新容量仍然低于所需的最小容量 (`minCapacity`),那么最终采用的是后者作为目标尺寸[^3]。 - **复制原有数据至更大的数组**:完成以上步骤之后,程序利用 `Arrays.copyOf()` 方法把现有内容迁移到更大规模的新数组里去[^3]。 以下是简化版的 `grow` 方法伪代码展示: ```java private void grow(int minCapacity) { int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; elementData = Arrays.copyOf(elementData, newCapacity); } ``` 这段代码片段清晰地体现了前面提到过的几个要点——基于旧容量增加一定比例形成候选新容量;必要时候直接采纳更高限值;最后借助工具类执行具体的数据迁移动作[^3]。 #### 4. 性能考量 尽管自动增长特性使得管理变得简单方便,但也需要注意频繁的小幅度扩展可能会带来性能开销,因为每次都需要重新分配内存并将已有项目逐一搬移过去。因此合理预估可能的最大装载量并通过适当配置初始容量可以帮助减少不必要的资源消耗[^1]。 --- ### 问题
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值