Skip to content
第 12 章 后端 ⏱ 10 分钟阅读

第 12 章:List 接口与 ArrayList ​

学习目标 ​

  • 掌握 List 接口的核心方法
  • 理解 ArrayList 和 LinkedList 的选型
  • 避开 List 的常见坑

一、List 接口:有序、可重复 ​

java
List<String> list = new ArrayList<>();

list.add("A");                  // ① 末尾添加
list.add(0, "B");               // ② 指定位置插入
list.get(0);                    // ③ 按索引访问
list.set(0, "C");               // ④ 修改
list.remove(0);                 // ⑤ 按索引删除
list.remove("A");               // ⑥ 按内容删除(删第一个匹配的)
list.size();                    // ⑦ 长度
list.contains("A");             // ⑧ 是否包含
list.indexOf("A");              // ⑨ 第一次出现的索引
list.isEmpty();                 // ⑩ 是否为空
list.clear();                   // 清空

遍历(三种方式):

java
List<String> list = List.of("A", "B", "C");

// ① for-each(只读,推荐)
for (String s : list) {
    System.out.println(s);
}

// ② 普通 for(需要索引时)
for (int i = 0; i < list.size(); i++) {
    System.out.println(i + ": " + list.get(i));
}

// ③ forEach + Lambda(Java 8+)
list.forEach(s -> System.out.println(s));

二、ArrayList vs LinkedList ​

维度ArrayListLinkedList
底层动态数组双向链表
随机访问(get)O(1) 快O(n) 慢
插入/删除O(n) 慢O(1) 快
内存占用少多(每个节点 2 个指针)

⚠️ 坑 1:99% 的场景用 ArrayList,除非是队列/栈等频繁增删两端元素的场景才用 LinkedList。

java
List<User> users = new ArrayList<>();  // ✅ 默认
Queue<Task> tasks = new LinkedList<>();  // ⚠️ 队列才用

三、ArrayList 常用 API 速查 ​

java
List<Integer> nums = new ArrayList<>(List.of(3, 1, 4, 1, 5));

nums.add(2);                  // 末尾加
nums.add(0, 9);               // 头部加
nums.get(0);                  // 取第 0 个
nums.set(0, 10);              // 改第 0 个
nums.remove(0);               // 删第 0 个(返回被删元素)
nums.remove(Integer.valueOf(1));  // 删第一个等于 1 的(注意装箱)
nums.size();
nums.contains(5);

Collections.sort(nums);       // 排序
Collections.reverse(nums);    // 反转
Collections.shuffle(nums);    // 随机打乱

⚠️ 坑 2:list.remove(0) 是按索引删;list.remove(Integer.valueOf(0)) 才是按内容删。直接 list.remove(0) 会把 0 当索引。

四、List 的常见坑 ​

1. 遍历时修改 ​

java
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));

// ❌ ConcurrentModificationException
for (Integer n : list) {
    if (n == 2) list.remove(n);   // 遍历时删除会抛异常
}

// ✅ 用迭代器
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    if (it.next() == 2) it.remove();
}

// ✅ 或反向遍历删除
for (int i = list.size() - 1; i >= 0; i--) {
    if (list.get(i) == 2) list.remove(i);
}

2. Arrays.asList 是固定大小 ​

java
List<String> list = Arrays.asList("a", "b", "c");
list.add("d");    // ❌ UnsupportedOperationException

// ✅ 包一层 ArrayList 才是可变
List<String> mutable = new ArrayList<>(Arrays.asList("a", "b", "c"));
mutable.add("d");

3. List.of 不可变 ​

java
List<String> list = List.of("a", "b", "c");
list.set(0, "x");  // ❌ UnsupportedOperationException
// 要可变?自己 new ArrayList<>()

五、本章小结 ​

要点关键
List 特性有序、可重复、可按索引访问
ArrayList99% 场景用,随机访问快
LinkedList仅队列/栈等场景用
遍历时删除用 Iterator 或反向遍历
Arrays.asList长度固定,add/remove 会抛异常,可以set
List.of不可变,完全不能改

动手练习 ​

  1. 学生列表:用 ArrayList 存 5 个学生,实现按名字查找、按成绩排序
  2. 删除偶数:写一个 removeEven(List<Integer>),注意遍历删除的坑
  3. 求最大值:用 List + for-each 求 List<Double> 的最大值

下一章:第 13 章:Set 接口与 HashSet →

本站基于 VitePress 构建 · 由 StackHub 团队维护