ArrayList 是 Java 集合框架中最常用、最基础的一个类,它实现了 List 接口,底层基于动态数组实现,这意味着它像数组一样,在内存中是连续存储的,因此具有以下特点:

(图片来源网络,侵删)
- 优点:
- 随机访问快:通过索引访问元素(
get(i))的时间复杂度是 O(1)。 - 尾部添加/删除快:在列表末尾添加或删除元素(
add(E),remove(size()-1))的时间复杂度平均为 O(1)。
- 随机访问快:通过索引访问元素(
- 缺点:
- 中间插入/删除慢:在列表中间或开头插入/删除元素时,需要移动大量元素,时间复杂度为 O(n)。
- 可能占用较多内存:为了实现动态扩容,
ArrayList内部通常会预留一部分容量。
构造方法
在开始使用方法前,你需要先创建一个 ArrayList 对象。
import java.util.ArrayList;
// 1. 创建一个空的 ArrayList,默认初始容量为 10
ArrayList<String> list1 = new ArrayList<>();
// 2. 创建一个空的 ArrayList,并指定初始容量(推荐,如果预估大小可避免多次扩容)
ArrayList<Integer> list2 = new ArrayList<>(20);
// 3. 创建一个 ArrayList,并用另一个集合(如另一个 ArrayList)初始化
ArrayList<String> initialList = new ArrayList<>(Arrays.asList("A", "B", "C"));
ArrayList<String> list3 = new ArrayList<>(initialList);
核心方法详解
我将方法按照功能进行分类,并附上代码示例。
添加元素
| 方法 | 描述 | 时间复杂度 | 示例 |
|---|---|---|---|
add(E e) |
将指定的元素添加到列表的末尾。 | O(1) (平均) | list.add("D"); |
add(int index, E e) |
将指定的元素插入到列表的指定位置。 | O(n) | list.add(1, "X"); // 在索引1处插入"X" |
addAll(Collection<? extends E> c) |
将指定集合中的所有元素追加到列表的末尾。 | O(m) (m为集合c的大小) | list.addAll(Arrays.asList("E", "F")); |
addAll(int index, Collection<? extends E> c) |
将指定集合中的所有元素从指定位置开始插入列表。 | O(n + m) | list.addAll(0, Arrays.asList("Y", "Z")); // 在开头插入 |
删除元素
| 方法 | 描述 | 时间复杂度 | 示例 |
|---|---|---|---|
remove(int index) |
移除列表中指定索引处的元素,并返回被移除的元素。 | O(n) | String removed = list.remove(0); // 移除第一个元素 |
remove(Object o) |
移除列表中第一次出现的指定元素,如果元素不存在,则列表不变。 | O(n) | list.remove("X"); // 移除第一个"X" |
clear() |
移除列表中的所有元素。 | O(n) | list.clear(); |
获取元素和查询
| 方法 | 描述 | 时间复杂度 | 示例 |
|---|---|---|---|
get(int index) |
返回列表中指定索引处的元素。 | O(1) | String first = list.get(0); |
size() |
返回列表中的元素数量(即列表的长度)。 | O(1) | int count = list.size(); |
isEmpty() |
如果列表不包含元素,则返回 true。 |
O(1) | boolean empty = list.isEmpty(); |
contains(Object o) |
如果列表中包含指定的元素,则返回 true。 |
O(n) | boolean hasB = list.contains("B"); |
indexOf(Object o) |
返回此列表中第一次出现的指定元素的索引,如果列表不包含该元素,则返回 -1。 | O(n) | int index = list.indexOf("F"); |
lastIndexOf(Object o) |
返回此列表中最后一次出现的指定元素的索引,如果列表不包含该元素,则返回 -1。 | O(n) | int lastIndex = list.lastIndexOf("F"); |
修改元素
| 方法 | 描述 | 时间复杂度 | 示例 |
|---|---|---|---|
set(int index, E e) |
用指定的元素替换列表中指定索引处的元素。 | O(1) | list.set(0, "New Element"); // 将第一个元素替换 |
子列表和视图
| 方法 | 描述 | 时间复杂度 | 示例 |
|---|---|---|---|
subList(int fromIndex, int toIndex) |
返回列表中从 fromIndex(包含)到 toIndex(不包含)部分的视图。 |
O(1) | List<String> sublist = list.subList(1, 3); // 获取索引1到2的子列表 |
⚠️ 重要提示:subList 返回的是一个视图,而不是一个新的独立列表,这意味着对子列表的任何修改(如 add, remove, set)都会直接反映到原始的 ArrayList 上,反之亦然。
ArrayList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
List<String> sublist = list.subList(1, 3); // sublist 是 ["B", "C"]
// 修改子列表
sublist.set(0, "X");
System.out.println(list); // 输出: [A, X, C, D, E] 原始列表被修改了!
// 在子列表上添加元素
sublist.add("Y");
System.out.println(list); // 输出: [A, X, C, Y, D, E] 原始列表也被修改了!
转换和其他实用方法
| 方法 | 描述 | 示例 |
|---|---|---|
toArray() |
将列表转换为一个对象数组 (Object[])。 |
Object[] objArray = list.toArray(); |
toArray(T[] a) |
将列表转换为一个指定类型的数组,更常用。 | String[] strArray = list.toArray(new String[0]); |
iterator() |
返回按适当顺序在列表的元素上进行迭代的迭代器。 | Iterator<String> it = list.iterator(); |
listIterator() |
返回列表中元素的列表迭代器(允许在迭代时进行双向遍历和修改)。 | ListIterator<String> lit = list.listIterator(); |
clone() |
返回此 ArrayList 实例的浅拷贝。 |
ArrayList<String> copy = (ArrayList<String>) list.clone(); |
完整代码示例
下面是一个综合运用上述方法的例子:

(图片来源网络,侵删)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 1. 创建并初始化
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));
System.out.println("初始列表: " + fruits);
// 2. 添加元素
fruits.add("Date"); // add(E)
System.out.println("添加 'Date' 后: " + fruits);
fruits.add(1, "Blueberry"); // add(int index, E e)
System.out.println("在索引1处添加 'Blueberry' 后: " + fruits);
// 3. 获取元素
String firstFruit = fruits.get(0);
System.out.println("第一个水果是: " + firstFruit);
// 4. 修改元素
fruits.set(2, "Blackberry"); // set(int index, E e)
System.out.println("将索引2的水果替换为 'Blackberry' 后: " + fruits);
// 5. 查询
System.out.println("列表大小: " + fruits.size());
System.out.println("列表是否包含 'Apple': " + fruits.contains("Apple"));
System.out.println("'Banana' 的索引是: " + fruits.indexOf("Banana"));
// 6. 删除元素
fruits.remove("Banana"); // remove(Object o)
System.out.println("移除 'Banana' 后: " + fruits);
String removedFruit = fruits.remove(1); // remove(int index)
System.out.println("移除索引1处的元素 '" + removedFruit + "' 后: " + fruits);
// 7. 子列表
List<String> subList = fruits.subList(1, 3);
System.out.println("子列表 (索引1到2): " + subList);
// 对子列表的修改会影响原列表
subList.set(0, "Fig");
System.out.println("修改子列表后,原列表变为: " + fruits);
// 8. 转换为数组
String[] fruitArray = fruits.toArray(new String[0]);
System.out.println("转换为数组: " + Arrays.toString(fruitArray));
// 9. 清空
fruits.clear();
System.out.println("清空后的列表: " + fruits);
System.out.println("列表是否为空: " + fruits.isEmpty());
}
}
遍历 ArrayList 的几种方式
-
For-Each 循环 (推荐):最简洁、最常用的方式。
for (String fruit : fruits) { System.out.println(fruit); } -
经典 For 循环:当你需要在遍历时获取元素的索引时使用。
for (int i = 0; i < fruits.size(); i++) { System.out.println("索引 " + i + ": " + fruits.get(i)); } -
使用
Iterator:可以在遍历时安全地删除元素。Iterator<String> iterator = fruits.iterator(); while (iterator.hasNext()) { String fruit = iterator.next(); if ("Apple".equals(fruit)) { iterator.remove(); // 安全删除 } } -
使用 Java 8 Stream API:适合进行复杂的链式操作(如过滤、映射)。
(图片来源网络,侵删)fruits.stream() .filter(f -> f.startsWith("A")) .forEach(System.out::println);
ArrayList vs. LinkedList
| 特性 | ArrayList |
LinkedList |
|---|---|---|
| 底层数据结构 | 动态数组 | 双向链表 |
随机访问 (get(i)) |
快 (O(1)) | 慢 (O(n)) |
| 头部/中间插入/删除 | 慢 (O(n)) | 快 (O(1)) |
| 尾部插入/删除 | 快 (O(1)) | 快 (O(1)) |
| 内存占用 | 较低(连续内存) | 较高(每个元素需额外存储前后指针) |
| 适用场景 | 频繁查询,少量增删 | 频繁增删,少量查询 |
希望这份详细的指南能帮助你全面掌握 Java ArrayList 的使用!
