ArrayList的自动扩容机制源码

Java的ArrayList的自动扩容机制


ArrayList是 Java 中极为常用的动态数组实现类,它依托数组存储数据,能依据实际需求灵活变动容量,高效管理元素集合。在深挖底层源码细节前,先来了解创建ArrayList集合并添加元素时的运作流程:

  • 默认初始化:空参构造时,ArrayList 使用一个长度为 0 的空数组,并不立即分配内存。
  • 首次添加:在首次添加元素时,数组容量初始化为 10。
  • 扩容机制:当数组满时,容量扩展为原来的 1.5 倍,以平衡性能与空间利用率。
  • 批量添加:使用 addAll() 方法时,容量直接扩展到满足新元素的实际需求,避免浪费。

成员变量

ArrayList 的核心成员变量如下:

private static final int DEFAULT_CAPACITY = 10; // 默认容量
private static final Object[] EMPTY_ELEMENTDATA = {}; // 空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空数组
transient Object[] elementData; // 数据存储数组
private int size; // 当前元素数量
  • DEFAULT_CAPACITY:默认初始容量为 10。
  • EMPTY_ELEMENTDATADEFAULTCAPACITY_EMPTY_ELEMENTDATA:两种不同场景下的空数组,前者表示完全空的集合,后者表示初始化容量为空但可扩展的集合。
  • elementData:存放实际数据的数组。
  • size:记录当前数组中的元素个数。

构造方法

ArrayList 提供了三种构造方法,其中常用的是空参构造方法:

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

工作机制

  • 空参构造方法并未立即分配内存,而是初始化一个长度为 0 的空数组 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
  • 真正分配内存发生在第一次添加元素时,数组容量会初始化为默认容量 10

add 方法

当我们调用 add 方法添加元素时,例如:

ArrayList<String> list = new ArrayList<>();
list.add("Hello");

以下是 add 方法的源码:

public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}

该方法调用了重载方法 add(E e, Object[] elementData, int size)


重载 add 方法解析

private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length) // 判断是否需要扩容
        elementData = grow();
    elementData[s] = e; // 将元素插入数组
    size = s + 1; // 更新 size
}

关键逻辑

  1. 扩容检查:如果当前数组已满(size == elementData.length),调用 grow 方法进行扩容。
  2. 新增元素:将元素插入数组的 size 位置,并将 size 自增 1。

grow 方法的扩容机制

扩容是动态数组的核心功能,其代码如下:

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

private int newCapacity(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1); // 扩容为原来的 1.5 倍
    return (newCapacity - minCapacity > 0) ? newCapacity : minCapacity;// 若实际长度更大,则扩容为实际长度
}

grow方法只完成了一件事,那就是将原本用来存放元素的数组拷贝到一个新的数组的当中完成扩容,新数组的长度为newCapacity(size)方法的返回值,也就是扩容后的长度
newCapacity(size)方法中传入了目前集合的长度size,并将其定义为了minCapacity,即最小容量,获取元素数组的长度定义为oldCapacity ,即旧容量大小,将旧的容量进行右移操作,使其大小变为原来的1/2,加上旧容量,定义为newCapacity ,即新容量的大小是旧容量大小的1.5倍,由此可见,默认的自动扩容机制扩容后的大小为原来的1.5倍,最后返回值为一个三元运算符,返回了较大的容量,也就是说1.5倍的容量满足不了当前的需求时,就会以实际的容量大小来进行扩容

逻辑详解

添加元素
数组已满吗
调用 grow 方法
计算新容量
1.5倍旧容量 >= 需要容量
使用 1.5倍旧容量
使用需要容量
复制数据到新数组
添加元素到数组
更新 size
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值