一、什么是 ArrayList
ArrayList 是 java.util 包下的类,实现了 List 接口,本质是动态扩容的数组(相比普通数组,它的长度可以自动调整)。
- 底层基于数组实现,支持快速随机访问(通过索引取值,时间复杂度 O (1))。
- 增删元素(尤其是中间位置)效率较低(需要移动元素,时间复杂度 O (n))。
- 允许存储
null值,且元素可重复,有序(按添加顺序保存)。
二、核心用法(完整示例代码)
以下是 ArrayList 最常用的操作,代码可直接复制运行:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ArrayListDemo {
public static void main(String[] args) {
// 1. 创建 ArrayList 对象(指定泛型,推荐,避免类型转换问题)
List<String> list = new ArrayList<>();
// 2. 添加元素
list.add("Java"); // 末尾添加
list.add("Python");
list.add(1, "C++"); // 指定索引(1)添加,原索引1及之后的元素后移
System.out.println("添加后:" + list); // 输出:[Java, C++, Python]
// 3. 获取元素
String first = list.get(0); // 通过索引获取,索引从0开始
System.out.println("第一个元素:" + first); // 输出:Java
// 4. 修改元素
list.set(2, "Go"); // 替换索引2的元素
System.out.println("修改后:" + list); // 输出:[Java, C++, Go]
// 5. 删除元素
list.remove(1); // 按索引删除
list.remove("Go"); // 按元素值删除
System.out.println("删除后:" + list); // 输出:[Java]
// 6. 遍历元素(三种常用方式)
// 方式1:for循环(按索引)
System.out.println("for循环遍历:");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 方式2:增强for循环
System.out.println("增强for循环遍历:");
for (String s : list) {
System.out.println(s);
}
// 方式3:迭代器
System.out.println("迭代器遍历:");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
// 7. 其他常用方法
int size = list.size(); // 获取元素个数
boolean isEmpty = list.isEmpty(); // 判断是否为空
boolean contains = list.contains("Java"); // 判断是否包含某个元素
list.clear(); // 清空所有元素
}
}
三、关键特性解析
-
扩容机制
- 初始容量默认是 10(JDK8 及以上),当元素个数超过当前容量时,会自动扩容为原来的 1.5 倍 (计算方式:
newCapacity = oldCapacity + (oldCapacity >> 1))。 - 如果提前知道元素数量,可通过
new ArrayList<>(指定容量)初始化,减少扩容次数,提升性能。
- 初始容量默认是 10(JDK8 及以上),当元素个数超过当前容量时,会自动扩容为原来的 1.5 倍 (计算方式:
-
线程安全
ArrayList是非线程安全 的,如果多线程同时读写ArrayList,可能会导致数据错乱。- 线程安全场景可使用:
Vector(古老的线程安全版,效率低)、Collections.synchronizedList(new ArrayList<>())、CopyOnWriteArrayList(高并发读场景推荐)。
-
与普通数组的区别
特性 ArrayList 普通数组 长度 动态扩容 固定长度 方法支持 丰富(add/remove 等) 仅通过索引操作 存储类型 只能存对象(基本类型自动装箱) 可存基本类型 / 对象
四、常见面试 / 使用注意点
-
遍历删除元素 :不能在增强 for 循环中直接删除元素(会抛
ConcurrentModificationException),需用迭代器的it.remove()方法。示例:List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); if (s.equals("a")) { it.remove(); // 正确删除方式 } } -
空指针风险 :
list.get(index)时,若索引越界(如 index >= list.size ()),会抛IndexOutOfBoundsException,使用前需校验索引合法性。
总结
ArrayList是基于动态数组的 List 实现,支持快速随机访问,增删中间元素效率低,有序、可重复、允许 null。- 核心操作包括添加(add)、获取(get)、修改(set)、删除(remove)、遍历,推荐指定泛型避免类型转换问题。
- 非线程安全,扩容默认 1.5 倍,遍历删除需用迭代器,提前指定容量可优化性能。
