目录
- 什么是
ArrayList? ArrayListvs 数组ArrayList的基本用法- 创建和初始化
- 添加元素
- 获取元素
- 修改元素
- 删除元素
- 获取大小
ArrayList的常用方法详解ArrayList的遍历方式ArrayList的注意事项- 线程安全性
- 泛型
null值
- 实战示例
什么是 ArrayList?
ArrayList 是 Java 集合框架中 List 接口的一个实现类,它的底层是一个动态数组,也就是说,它的容量是可以自动增长的。

- 特点:
- 有序:元素的存取顺序是一致的。
- 可重复:可以存储重复的元素。
- 动态扩容:当元素数量超过当前容量时,
ArrayList会自动扩容(通常是原容量的 1.5 倍)。 - 随机访问快:基于数组实现,可以通过索引(下标)快速访问任意位置的元素,时间复杂度为 O(1)。
- 增删中间元素慢:在中间插入或删除元素时,需要移动大量元素,时间复杂度为 O(n)。
ArrayList vs 数组
在深入 ArrayList 之前,先理解它和传统数组的区别非常重要。
| 特性 | 数组 | ArrayList |
|---|---|---|
| 大小 | 固定,创建时必须指定大小,之后无法改变。 | 动态,可以随时添加或删除元素,大小自动调整。 |
| 类型 | 可以存储基本类型(如 int[])和对象(如 String[])。 |
只能存储对象,对于基本类型,需要使用其对应的包装类(如 Integer 代替 int)。 |
| 功能 | 功能简单,只有 length 属性和一些基本操作。 |
功能丰富,提供了大量方法,如 add(), remove(), size(), sort() 等。 |
| 性能 | 访问速度快,增删慢(因为大小固定)。 | 随机访问快,增删中间元素慢。 |
如果你需要存储一个固定数量、已知类型的数据,数组是轻量级的选择,如果你需要一个可以动态改变大小的集合,并且需要丰富的操作方法,ArrayList 是不二之选。
ArrayList 的基本用法
1 创建和初始化
最常用的方式是使用泛型来指定 ArrayList 中要存储的元素类型。
// 1. 创建一个空的、初始容量为 10 的 ArrayList
// 推荐使用泛型,指定存放 String 类型
ArrayList<String> stringList = new ArrayList<>();
// 2. 创建一个指定初始容量的 ArrayList
// 如果大概知道要存多少元素,可以指定初始容量以减少扩容操作
ArrayList<Integer> numberList = new ArrayList<>(20);
// 3. 使用集合初始化(Java 9+)
// List.of() 创建的是一个不可变列表,不能添加或删除元素
// 如果需要一个可变的 ArrayList,可以这样转换
List<String> initialList = List.of("Apple", "Banana", "Cherry");
ArrayList<String> fruitList = new ArrayList<>(initialList);
2 添加元素
使用 add() 方法。

ArrayList<String> colors = new ArrayList<>();
// 在列表末尾添加元素
colors.add("Red");
colors.add("Green");
colors.add("Blue");
// 在指定位置插入元素
colors.add(1, "Yellow"); // 在索引 1 的位置插入 "Yellow"
// colors 现在是: ["Red", "Yellow", "Green", "Blue"]
3 获取元素
使用 get(int index) 方法,索引从 0 开始。
ArrayList<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue"));
String firstColor = colors.get(0); // 获取第一个元素
System.out.println("The first color is: " + firstColor); // 输出: The first color is: Red
4 修改元素
使用 set(int index, E element) 方法。
ArrayList<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue"));
// 修改索引 1 处的元素
colors.set(1, "Orange");
// colors 现在是: ["Red", "Orange", "Blue"]
System.out.println(colors); // 输出: [Red, Orange, Blue]
5 删除元素
有两种常用方式:
remove(int index):删除指定索引位置的元素。remove(Object o):删除第一个匹配的元素。
ArrayList<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue", "Green"));
// 删除索引为 2 的元素
colors.remove(2); // 删除 "Blue"
// colors 现在是: ["Red", "Green", "Green"]
// 删除第一个值为 "Green" 的元素
colors.remove("Green");
// colors 现在是: ["Red", "Green"]
6 获取大小
使用 size() 方法,它返回列表中的元素数量。

ArrayList<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue"));
int size = colors.size();
System.out.println("The size of the list is: " + size); // 输出: The size of the list is: 3
ArrayList 的常用方法详解
| 方法 | 描述 |
|---|---|
add(E e) |
将指定的元素追加到此列表的末尾。 |
add(int index, E element) |
在此列表的指定位置插入指定的元素。 |
get(int index) |
返回此列表中指定位置的元素。 |
set(int index, E element) |
用指定的元素替换此列表中指定位置的元素。 |
remove(int index) |
移除此列表中指定位置的元素。 |
remove(Object o) |
移除此列表中首次出现的指定元素(如果存在)。 |
size() |
返回此列表中的元素数。 |
isEmpty() |
如果此列表不包含元素,则返回 true。 |
clear() |
从此列表中移除所有元素。 |
contains(Object o) |
如果此列表包含指定的元素,则返回 true。 |
indexOf(Object o) |
返回此列表中首次出现的指定元素的索引,如果此列表不包含该元素,则返回 -1。 |
lastIndexOf(Object o) |
返回此列表中最后出现的指定元素的索引,如果此列表不包含该元素,则返回 -1。 |
toArray() |
以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 |
ArrayList 的遍历方式
遍历是操作集合最频繁的操作之一,主要有四种方式。
ArrayList<String> fruits = new ArrayList<>(List.of("Apple", "Banana", "Cherry"));
// 1. for 循环(通过索引遍历)
// 最传统的方式,适用于需要知道索引的场景
System.out.println("--- For Loop ---");
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
}
// 2. 增强 for 循环 (for-each)
// 最简洁、最推荐的方式,适用于简单遍历
System.out.println("\n--- Enhanced For Loop ---");
for (String fruit : fruits) {
System.out.println(fruit);
}
// 3. 使用 Iterator (迭代器)
// 适用于在遍历过程中需要安全地删除元素的场景
System.out.println("\n--- Iterator ---");
Iterator<String> iterator = fruits.iterator();
while (iterator.hasNext()) {
String fruit = iterator.next();
// 使用 iterator.remove() 来删除当前元素,而不是 list.remove()
// if ("Banana".equals(fruit)) {
// iterator.remove();
// }
System.out.println(fruit);
}
// 4. 使用 Java 8+ 的 Stream API
// 非常强大,支持链式操作和并行处理
System.out.println("\n--- Stream API ---");
fruits.stream().forEach(System.out::println);
ArrayList 的注意事项
1 线程安全性
ArrayList 不是线程安全 的,如果在多线程环境下对同一个 ArrayList 实例进行并发修改,可能会导致数据不一致或 ConcurrentModificationException 异常。
解决方案:
- 如果需要线程安全的
List,可以使用Collections.synchronizedList(new ArrayList<>())。 - 更推荐使用
java.util.concurrent.CopyOnWriteArrayList,它专为并发场景设计。
// 方式1: 使用 Collections 工具类 List<String> syncList = Collections.synchronizedList(new ArrayList<>()); // 方式2: 使用 CopyOnWriteArrayList List<String> cowList = new CopyOnWriteArrayList<>();
2 泛型
强烈建议在创建 ArrayList 时使用泛型,这样可以:
- 类型安全:编译器会检查你存入的元素类型是否正确。
- 避免强制类型转换:从
get()方法获取元素时,不需要手动强制转换。
// 好的实践
ArrayList<String> list = new ArrayList<>();
list.add("Hello");
String s = list.get(0); // 无需强制转换
// 不好的实践(不使用泛型)
ArrayList rawList = new ArrayList();
rawList.add("Hello");
rawList.add(123); // 编译器不会报错,但非常危险
String s1 = (String) rawList.get(0); // 需要强制转换
String s2 = (String) rawList.get(1); // 运行时抛出 ClassCastException
3 null 值
ArrayList 可以存储 null 值,但在使用 remove(Object o) 方法时要注意,它会移除第一个匹配的 null。
ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add(null);
list.add("B");
list.add(null);
list.remove(null); // 移除第一个 null
// list 现在是: ["A", "B", null]
实战示例
下面是一个综合示例,演示了如何创建、添加、遍历、修改和删除一个 ArrayList。
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListDemo {
public static void main(String[] args) {
// 1. 创建一个 ArrayList 来存储学生对象
ArrayList<Student> studentList = new ArrayList<>();
// 2. 添加学生
studentList.add(new Student("张三", 20));
studentList.add(new Student("李四", 22));
studentList.add(new Student("王五", 21));
// 3. 遍历并打印所有学生信息
System.out.println("--- 初始学生列表 ---");
for (Student student : studentList) {
System.out.println(student);
}
// 4. 在指定位置插入学生
studentList.add(1, new Student("赵六", 19));
System.out.println("\n--- 插入学生后 ---");
studentList.forEach(System.out::println);
// 5. 修改学生信息
studentList.get(0).setAge(21);
System.out.println("\n--- 修改张三年龄后 ---");
System.out.println(studentList.get(0));
// 6. 删除学生
studentList.remove("王五"); // 注意:需要 Student 类重写 equals 方法
System.out.println("\n--- 删除王五后 ---");
Iterator<Student> iterator = studentList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
// 7. 获取列表大小
System.out.println("\n--- 最终列表大小 ---");
System.out.println("学生总数: " + studentList.size());
}
}
// 一个简单的 Student 类
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
// 重写 equals 方法,以便可以通过 remove(Object o) 删除
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && name.equals(student.name);
}
}
ArrayList 是 Java 开发中必须掌握的工具,它的核心优势在于动态大小和随机访问的快速性,记住它的主要特点、常用方法和注意事项,特别是线程不安全和泛型的使用,你就能在日常开发中灵活、高效地运用它。
