🟦 Java ArrayList 详解

1️⃣ 什么是 ArrayList?

  • ArrayList 是 Java 集合框架(java.util 包)中的一个类。
  • 本质:基于 动态数组 实现的 可变长列表
  • 特点:
    • 元素有序(插入顺序就是存储顺序)。
    • 允许存放 重复元素
    • 允许存放 null
    • 底层通过 数组扩容机制 实现自动增长。

👉 和 数组 (array[]) 的区别:

  • 数组:长度固定,声明时必须指定大小。
  • ArrayList:长度可变,存放的元素数量可以动态增减。

2️⃣ ArrayList 的定义与初始化

import java.util.ArrayList;

public class TestArrayList {
    public static void main(String[] args) {
        // 1. 创建一个空的 ArrayList(默认容量为 10)
        ArrayList<String> list1 = new ArrayList<>();

        // 2. 指定初始容量
        ArrayList<Integer> list2 = new ArrayList<>(20);

        // 3. 通过另一个集合初始化
        ArrayList<String> list3 = new ArrayList<>(list1);
    }
}


3️⃣ 常用方法

(1)添加元素

ArrayList<String> list = new ArrayList<>();
list.add("苹果");
list.add("香蕉");
list.add("橙子");

// 在指定位置插入
list.add(1, "草莓"); // [苹果, 草莓, 香蕉, 橙子]

(2)访问元素

String fruit = list.get(2); // 获取下标为 2 的元素 -> 香蕉

(3)修改元素

list.set(0, "榴莲"); // 修改下标 0 的元素 -> [榴莲, 草莓, 香蕉, 橙子]

(4)删除元素

list.remove(1);        // 按下标删除 -> 删除草莓
list.remove("橙子");   // 按对象删除 -> 删除橙子
list.clear();          // 清空所有元素

(5)查询

list.add("苹果");
list.add("香蕉");
System.out.println(list.contains("苹果")); // true
System.out.println(list.indexOf("苹果"));  // 0
System.out.println(list.isEmpty());       // false
System.out.println(list.size());          // 2


4️⃣ 遍历方式

ArrayList<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");

// 1. for 循环
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

// 2. 增强 for 循环
for (String item : list) {
    System.out.println(item);
}

// 3. Iterator 迭代器
import java.util.Iterator;
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

// 4. Java 8 Lambda 表达式
list.forEach(e -> System.out.println(e));


5️⃣ ArrayList 底层原理(扩容机制)

  • 底层是 动态数组Object[] elementData)。
  • 默认初始容量 = 10。
  • 当元素数量 > 当前数组容量时,会 自动扩容
    • 新容量 = 原容量 × 1.5 (即增加 50%)。
    • 把旧数组数据拷贝到新数组。

👉 因此:

  • 频繁扩容会有性能开销(复制数组)。
  • 如果能预估数据量,建议在创建时指定容量: ArrayList<Integer> list = new ArrayList<>(1000);

6️⃣ 与 LinkedList 的区别

特点ArrayListLinkedList
底层实现动态数组双向链表
随机访问O(1) 速度快O(n) 速度慢
插入删除中间位置较慢(需要移动元素)任意位置都较快(只需修改指针)
内存开销较小较大(存储指针)

👉 使用建议:

  • 随机访问多(如根据下标访问元素):用 ArrayList
  • 频繁插入删除:用 LinkedList

7️⃣ 常见坑 ⚠️

  1. 边遍历边删除会出错 for (String item : list) { if (item.equals("A")) { list.remove(item); // ❌ 会报 ConcurrentModificationException } } ✅ 正确写法:用 Iterator Iterator<String> it = list.iterator(); while (it.hasNext()) { if (it.next().equals("A")) { it.remove(); // 正确 } }
  2. 线程不安全
    • ArrayList 不是线程安全的。
    • 多线程环境用 Collections.synchronizedList()CopyOnWriteArrayList

8️⃣ 使用场景

  • 存储一组有序数据,需要 快速随机访问
  • 适合存放 查询多、修改少 的数据。
  • 常用于缓存、批量处理、需要排序的场景。

📝 总结

  • ArrayList 本质:动态数组,可自动扩容。
  • 特点:有序、允许重复、可存 null
  • 底层机制:默认容量 10,扩容为 1.5 倍。
  • 优点:查询快。
  • 缺点:插入删除慢、线程不安全。
  • 最佳实践:查询多 → ArrayList,增删多 → LinkedList。