什么是 ArrayList?
ArrayList 是 Java 集合框架中 List 接口的一个可调整大小的数组实现,它就是一个可以动态改变长度的数组。

与 Java 中固定长度的原生数组(int[], String[] 等)相比,ArrayList 提供了更灵活、更强大的功能,是开发中处理动态数据集合的首选。
核心特点:
- 有序性:
ArrayList中的元素会按照插入的顺序进行存储(也称为“插入顺序”)。 - 允许重复:可以存储多个重复的元素。
- 允许 null 元素:可以存储
null值。 - 非线程安全:在多线程环境下,如果多个线程同时修改一个
ArrayList,可能会导致数据不一致,如果需要线程安全,可以使用Collections.synchronizedList(new ArrayList<>())或CopyOnWriteArrayList。 - 基于数组:它的底层实现是一个动态数组,这使得它在随机访问(通过索引)元素时非常快,时间复杂度为 O(1)。
如何创建和初始化 ArrayList?
创建 ArrayList 通常有两种方式:指定初始容量和不指定。
1 基本语法
// 1. 创建一个空的 ArrayList,默认初始容量是 10
ArrayList<String> list1 = new ArrayList<>();
// 2. 创建一个指定初始容量的 ArrayList
// 如果大概知道要存储多少元素,指定初始容量可以提高性能,避免多次扩容
ArrayList<Integer> list2 = new ArrayList<>(20);
// 3. 使用 Java 7 的 "菱形语法" (Diamond Syntax)
// 编译器会自动推断泛型类型
ArrayList<Double> list3 = new ArrayList<>();
// 4. 从一个已有的集合创建 ArrayList
// 从一个数组创建
String[] array = {"A", "B", "C"};
ArrayList<String> list4 = new ArrayList<>(Arrays.asList(array));
2 注意事项:泛型
ArrayList<String> 中的 <String> 就是泛型,它规定了这个 ArrayList 只能存储 String 类型的对象,这提供了类型安全,避免了在运行时出现 ClassCastException。

ArrayList<String>:只能存String。ArrayList<Integer>:只能存Integer(注意,不能存基本类型int,要使用其包装类)。ArrayList<Object>:可以存任何类型的对象。
如果不使用泛型,ArrayList 默认可以存储任何 Object 类型的对象,但非常不推荐,因为它失去了编译期的类型检查。
// 不推荐的方式,可能导致运行时错误
ArrayList list = new ArrayList();
list.add("Hello");
list.add(123);
String str = (String) list.get(0); // 需要强制转换,且容易出错
常用方法
以下是 ArrayList 最常用的一些方法,并附有示例。
1 添加元素
| 方法 | 描述 | 示例 |
|---|---|---|
add(E e) |
在列表的末尾添加一个元素。 | list.add("Apple"); |
add(int index, E e) |
在列表的指定位置插入一个元素。 | list.add(0, "Banana"); // 插入到开头 |
ArrayList<String> fruits = new ArrayList<>();
fruits.add("Apple"); // 添加 "Apple"
fruits.add("Orange"); // 添加 "Orange"
fruits.add(1, "Banana"); // 在索引 1 的位置插入 "Banana"
// fruits 现在是: ["Apple", "Banana", "Orange"]
2 访问元素
| 方法 | 描述 | 示例 |
|---|---|---|
get(int index) |
返回列表中指定位置的元素。 | String fruit = fruits.get(0); |
size() |
返回列表中的元素数量(即长度)。 | int count = fruits.size(); |
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Orange"));
String firstFruit = fruits.get(0); // firstFruit 是 "Apple"
int size = fruits.size(); // size 是 3
3 修改元素
| 方法 | 描述 | 示例 |
|---|---|---|
set(int index, E e) |
用指定的元素替换列表中指定位置的元素。 | fruits.set(0, "Grape"); |
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Orange"));
fruits.set(0, "Grape"); // 将索引 0 的 "Apple" 替换为 "Grape"
// fruits 现在是: ["Grape", "Banana", "Orange"]
4 删除元素
| 方法 | 描述 | 示例 |
|---|---|---|
remove(int index) |
移除列表中指定位置的元素。 | fruits.remove(0); // 移除第一个元素 |
remove(Object o) |
移除列表中第一次出现的指定元素。 | fruits.remove("Banana"); |
ArrayList<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Orange", "Banana"));
// 按索引删除
fruits.remove(0); // 移除 "Apple"
// fruits 现在是: ["Banana", "Orange", "Banana"]
// 按对象删除
fruits.remove("Banana"); // 移除第一个 "Banana"
// fruits 现在是: ["Orange", "Banana"]
5 遍历 ArrayList
遍历是操作集合最常见的操作,有三种主要方式:
-
使用 for 循环(通过索引)
(图片来源网络,侵删)for (int i = 0; i < fruits.size(); i++) { System.out.println(fruits.get(i)); } -
使用 for-each 循环(增强型 for 循环) - 最推荐 这种方式代码更简洁,并且避免了索引越界的风险。
for (String fruit : fruits) { System.out.println(fruit); } -
使用迭代器 迭代器提供了一种更安全的方式来遍历和修改集合,特别是在遍历过程中需要删除元素时。
Iterator<String> iterator = fruits.iterator(); while (iterator.hasNext()) { String fruit = iterator.next(); System.out.println(fruit); // 如果需要删除元素,必须使用迭代器的 remove 方法 // iterator.remove(); }
6 其他实用方法
| 方法 | 描述 | 示例 |
|---|---|---|
contains(Object o) |
如果列表包含指定的元素,则返回 true。 |
boolean hasApple = fruits.contains("Apple"); |
isEmpty() |
如果列表不包含元素,则返回 true。 |
boolean isEmpty = fruits.isEmpty(); |
clear() |
移除列表中的所有元素。 | fruits.clear(); |
toArray() |
将列表转换为一个数组。 | Object[] array = fruits.toArray(); |
ArrayList vs. 原生数组
| 特性 | ArrayList |
原生数组 (T[]) |
|---|---|---|
| 长度 | 可动态调整,自动处理扩容和缩容。 | 固定长度,创建后不能改变。 |
| 性能 | 随机访问快 (O(1)),在中间/头部插入/删除慢 (O(n)),因为需要移动元素。 | 随机访问极快 (O(1)),插入/删除慢 (O(n))。 |
| 类型安全 | 通过泛型在编译期提供类型安全。 | 通过声明类型(如 String[])提供类型安全。 |
| 功能 | 提供丰富的 API(add, remove, size, contains 等)。 |
功能非常基础,只有 length 属性和 [] 访问。 |
| 使用场景 | 当元素数量不确定,需要频繁增删改查时。 | 当元素数量固定,且对性能要求极高(尤其是内存)时。 |
示例代码
下面是一个完整的示例,展示了 ArrayList 的基本用法:
import java.util.ArrayList;
import java.util.Arrays;
public class ArrayListExample {
public static void main(String[] args) {
// 1. 创建 ArrayList
ArrayList<String> students = new ArrayList<>();
// 2. 添加元素
System.out.println("添加元素...");
students.add("张三");
students.add("李四");
students.add("王五");
System.out.println("当前学生列表: " + students); // 自动调用 toString() 方法
// 3. 在指定位置插入
students.add(1, "赵六");
System.out.println("在索引1处插入'赵六'后: " + students);
// 4. 访问元素
System.out.println("\n访问元素...");
String firstStudent = students.get(0);
System.out.println("第一个学生是: " + firstStudent);
System.out.println("学生总数: " + students.size());
// 5. 修改元素
System.out.println("\n修改元素...");
students.set(0, "张三丰");
System.out.println("将第一个学生修改为'张三丰'后: " + students);
// 6. 删除元素
System.out.println("\n删除元素...");
students.remove("赵六"); // 按对象删除
System.out.println("删除'赵六'后: " + students);
students.remove(0); // 按索引删除
System.out.println("删除第一个学生后: " + students);
// 7. 遍历 ArrayList
System.out.println("\n遍历学生列表:");
for (String student : students) {
System.out.println("- " + student);
}
// 8. 检查元素是否存在
System.out.println("\n检查元素是否存在...");
boolean hasLiSi = students.contains("李四");
System.out.println("列表中是否包含'李四'? " + hasLiSi);
// 9. 清空列表
System.out.println("\n清空列表...");
students.clear();
System.out.println("列表是否为空? " + students.isEmpty());
System.out.println("最终列表: " + students);
}
}
ArrayList 是 Java 开发中必须掌握的核心工具,它像一个功能更强大的“动态数组”,解决了原生数组长度固定的痛点,记住它的核心特点:
- 基于数组,随机访问快。
- 非线程安全。
- 有序、可重复。
- 通过泛型保证类型安全。
熟练掌握 ArrayList 的创建、增、删、改、查、遍历等基本操作,是进行 Java 开发的基础。
