Java ArrayList类用法详解与源码深度解析

七月
七月
发布时间:2026-10-13| 6人浏览过
原创

Java中的ArrayList是开发中最常用的集合类之一,其内部基于可变长数组实现。它支持元素的动态增删、高效的随机访问以及多种遍历和搜索方式。本文将全面解析ArrayList的核心操作方法,并深入其源码设计,揭示数组自动扩容与数据转移的底层逻辑。

ArrayList的基础特性

ArrayList位于java.util包下,是List接口的一个具体实现类。与定长的数组相比,它的最大优势在于可以自动改变大小。当向其中添加大量元素时,它会根据需要动态分配内存空间;在不需要时,也可以手动收缩以释放内存。

优点:

  • 支持自动改变大小的功能。
  • 可以快速通过索引访问指定位置的元素,时间复杂度为O(1)。
  • 插入和删除元素(尤其是尾部)相对灵活。

局限性:

由于底层使用数组,在指定位置进行非尾部的插入或删除时,会涉及其后所有元素的位移,速度较直接添加或删除稍慢,时间复杂度为O(n)。

ArrayList的核心操作方法

掌握ArrayList的日常使用方法,需要重点关注增、删、查、改、判空及容量调整这几大模块。

第1步:向列表中添加元素

目的:将单个对象或集合添加到列表中,这是构建初始数据最常用的操作。

  • Add(E e):将指定的元素追加到此列表的末尾。示例如下:
ArrayList list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
// 结果为 ["a", "b", "c"]
  • Add(int index, E element):将指定元素插入到指定位置。此操作会将当前处于该位置及其后续的元素向后移动一位。
list.add(0, "aa");
// 结果为 ["aa", "a", "b", "c"]
  • AddAll(Collection c):按指定集合的迭代器返回的顺序,将所有元素追加到列表的末尾。

第2步:从列表中移除元素

目的:清理不再需要的数据,保持列表的准确性。

  • Remove(Object o):移除此列表中首次出现的指定元素(如果存在)。注意:这里匹配的是equals方法,若列表中有重复元素,仅移除第一个。
list.remove("a");
// 结果为 ["b", "c"]
  • Remove(int index):移除列表中指定位置的元素。该操作会将随后的元素向左移动一个位置。
list.remove(0);
// 结果为 ["b", "c"]
  • clear():移除列表中的所有元素。调用后,列表的长度变为零。

第3步:获取与查找元素

目的:确定元素的存在性及所在位置。

  • get(int index):返回列表中指定位置的元素。使用前需确保索引不越界。
String item = list.get(1); // 取出 "b"
  • indexOf(Object o):返回此列表中首次出现指定元素的索引,如果此列表不包含该元素,则返回 -1。
int index = list.indexOf("b"); // 值为 1
  • lastIndexOf(Object o):返回此列表中最后一次出现指定元素的索引,未找到返回 -1。
ArrayList dupList = new ArrayList<>();
dupList.add("a");
dupList.add("b");
dupList.add("a");
int lastIdx = dupList.lastIndexOf("a"); // 值为 2 而不是 0
  • contains(Object o):判断列表是否包含特定元素,包含返回true,否则返回false。

第4步:修改与遍历顺序

  • set(int index, E element):用指定元素替换列表中指定位置的元素,并返回被替换的旧值。
list.set(0, "xx");
// 列表第一个元素由原来的 "a" 变成了 "xx"
  • sort():根据元素的自然顺序对列表进行排序(要求元素实现Comparable接口,或使用Collections.sort(list))。
list.add("e");
list.add("a");
Collections.sort(list);
// 结果为 ["a", "e"]
  • reverse():反转列表中元素的顺序(通常配合 Collections.reverse() 使用)。

第5步:管理容量(Capacity)与内存

目的:优化内存使用,避免不必要的数组空间浪费。

  • Count vs Capacity: size() 表示当前列表中实际包含的元素个数;而 capacity 是其底层数组能够容纳的最大数量。默认情况下,创建一个空的 ArrayList 时 capacity 为 16。
  • trimToSize():将此 ArrayList 实例的容量调整为列表的当前大小。如果不打算向列表中添加新元素,可以调用此方法来最小化存储开销。
ArrayList trimmedList = new ArrayList<>(50);
trimmedList.add("test");
// 初始容量可能为 50,此时 size=1
trimmedList.trimToSize();
// 执行后,capacity 将缩减至 1,节省了大量内存

ArrayList源码深度解析

理解ArrayList为何能“动态”扩展,关键在于探究其底层的数组扩容与复制机制。ArrayList实现了Cloneable、Serializable、List和RandomAccess接口。其中,RandomAccess标记用于告知通用算法(如二分查找),针对此类列表进行快速随机访问是高效的。

第1步:初始化与构造器

ArrayList内部维护了一个Object类型的数组elementData。在默认无参构造函数中,实际上并不会立即分配大小为10或16的数组,而是赋值为空数组{},只有第一次调用add时才进行真正的初始化。

一旦开始填充数据,默认初始容量会被设定为 10(旧版本)或在某些JDK实现中按需触发第一次扩容。以下是标准的扩容核心代码:grow 方法。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // 核心算法:新容量 = 旧容量 + (旧容量 >> 1),即增加 50%
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // 将旧数组的数据复制到新分配的更大的数组中
    elementData = Arrays.copyOf(elementData, newCapacity);
}

第2步:插入元素时的数组位移

当向非末尾位置插入元素时(例如 add(index, element)),为了保证元素的连续性,Java使用了系统级的数组拷贝函数 System.arraycopy。这个原生方法比普通的for循环逐个赋值快得多。

例如向索引2处插入新元素:需要将原索引2及之后的所有元素整体向后平移一位。

// System.arraycopy(src, srcPos, dest, destPos, length)
System.arraycopy(elementData, index, elementData, index + 1, size - index);

第3步:删除元素时的处理

删除某个元素时,同样需要利用 System.arraycopy 将后继元素前移填补空缺,并将原位置上最后的引用置为null以便垃圾回收器回收该对象。

private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    // 从 index+1 开始的所有元素移动到 index 位置
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index, numMoved);
    // 清除最后一个位置,防止内存泄漏
    elementData[--size] = null; 
}

总结

Java中的ArrayList凭借其灵活的动态扩容能力成为了日常编程的首选容器。开发者在日常使用时,应明确其基于数组的特性,尽量使用尾插法来避免频繁的数组位移操作。同时,在对内存敏感的场景下,可以通过预估数据量设置合适的初始容量,或在使用完毕后调用 trimToSize() 减少冗余占用。以上就是ArrayList类的用法与源码分析的详细内容,更多关于Java集合框架的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。