---
title: "00-List总览"
created: 2025-12-02
tags:
- Java
---
# List
> [!note] 定位说明
> 本篇是 List 系列的总览:先建立"List 是什么、三实现怎么选"的整体认知,再进入各实现类详篇。动线:本篇 → [[01-ArrayList|ArrayList]] → [[02-LinkedList|LinkedList]] → [[03-Vector|Vector]]。
**Java 中的 List 接口:有序、可重复的集合框架核心**
List 是 Java 集合框架中最常用的接口之一,继承自`Collection`,具有以下核心特性:
- **有序性**:元素按插入顺序存储,支持通过索引(下标)访问元素。
- **可重复性**:允许存储重复元素。
- **丰富的操作接口**:提供`get(int index)`、`add(int index, E element)`、`remove(int index)`等基于索引的操作方法,方便数据的随机访问和位置调整。
## 继承关系
```mermaid
graph TD
Iterable["Iterable<E>"] --> Collection["Collection<E>"]
Collection --> List["List<E>"]
List --> ArrayList["ArrayList
动态数组"]
List --> LinkedList["LinkedList
双向链表"]
List --> Vector["Vector
同步动态数组(遗留)"]
Vector --> Stack["Stack
栈(遗留)"]
```
一句话记忆:**List = 可按下标操作的动态序列**。ArrayList 是默认选择,LinkedList 换来了头尾操作的高效,Vector 是历史遗留(见其篇内"为什么现在不用 Vector")。
List 接口有多个实现类:[[01-ArrayList|ArrayList]]、[[02-LinkedList|LinkedList]]、[[03-Vector|Vector]]
| **维度** | **ArrayList** | **LinkedList** | **Vector** |
| --- | --- | --- | --- |
| **底层结构** | 动态数组(`Object[]`,连续内存) | 双向链表(`Node`节点,非连续内存) | 动态数组(`Object[]`,连续内存) |
| **线程安全** | ❌ 非线程安全 | ❌ 非线程安全 | ✅ 线程安全(方法加 `synchronized`) |
| **随机访问效率** | ✅ 快速(O (1),索引直接定位) | ❌ 低效(O (n),需遍历链表) | ✅ 快速(O (1),索引直接定位) |
| **插入 / 删除效率** | ❌ 尾部 O (1)(若需扩容则 O (n)) 中间 O (n)(移动元素) | ✅ 头尾 O (1)(改指针) 中间 O (n)(遍历定位) | ❌ 尾部 O (1)(若需扩容则 O (n)) 中间 O (n)(移动元素) |
| **扩容机制** | 自动扩容(默认初始 10,1.5 倍增长) | 无需扩容(链表天然动态) | 自动扩容(默认初始 10,**2 倍增长**) |
| **内存开销** | 较小(数组紧凑存储,无额外指针) | 较大(每个节点需存储 `prev` 和 `next` 指针) | 较大(同步机制额外开销 + 数组存储) |
| **Null 元素支持** | ✅ 可存储多个 `null` | ✅ 可存储多个 `null` | ✅ 可存储多个 `null` |
| **适用场景** | 单线程、读多写少、随机访问频繁 (如缓存、索引表、数据库结果集) | 单线程、写多读少、频繁头尾操作 (如消息队列、栈 / 队列、链式数据结构) | 多线程、需要线程安全的随机访问场景 (如共享数据读写、旧系统兼容) |
| **典型应用** | `for` 循环遍历、排行榜(需索引) | `Deque` 双端队列、LRU 缓存(头尾操作) | 多线程计数器、共享日志列表 |
| **替代方案** | 多线程时用 `Collections.synchronizedList()` 或 `CopyOnWriteArrayList` | 多线程时用 `ConcurrentLinkedQueue` | 优先用 `ArrayList + 同步包装` 或 `CopyOnWriteArrayList` |
## 常用方法速查
```java
List list = new ArrayList<>();
list.add("b"); // 尾部追加
list.add(0, "a"); // 指定位置插入(后面的元素整体后移)
list.set(0, "A"); // 覆盖指定位置元素,返回旧值
list.get(0); // 按下标取值
list.remove(0); // 按下标删(注意重载歧义,见下)
list.remove("A"); // 按对象删(equals 判等)
list.indexOf("A"); // 第一次出现的下标,没有返回 -1
list.contains("A"); // 是否包含(底层 indexOf)
list.size(); // 元素个数
list.isEmpty(); // 是否为空
list.sort(Comparator.comparingInt(String::length)); // 就地排序
list.subList(0, 2); // 截取 [0,2) 视图——改视图会影响原 List
list.clear(); // 清空
```
> [!warning] `remove` 的重载歧义(高频面试坑)
> `List list` 里调 `remove(1)` 删的是**下标 1**,不是元素 `1`——因为 `remove(int index)` 精确匹配优先于 `remove(Object o)`。要按元素删必须写 `list.remove(Integer.valueOf(1))`。
## 遍历的四种方式
```java
List list = List.of("a", "b", "c");
// 1. 普通for——需要下标时用
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 2. 增强for——只读遍历的首选
for (String s : list) {
System.out.println(s);
}
// 3. Iterator——遍历中要删元素时唯一安全的方式(fail-fast 见 ArrayList 篇)
Iterator it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("a".equals(s)) it.remove(); // 用迭代器自己的 remove,不是 list.remove
}
// 4. ListIterator——List 独有,可双向遍历、可修改
ListIterator lit = list.listIterator();
while (lit.hasNext()) {
String s = lit.next();
lit.set(s.toUpperCase()); // 边遍历边改
}
while (lit.hasPrevious()) { // 此时光标在末尾,可反向再走一遍
System.out.println(lit.previous());
}
```
## 创建 List 的三种姿势(面试高频)
```java
// 1. new —— 可变,日常主力
List a = new ArrayList<>();
a.add("x"); // ✅ 可以增删改
// 2. Arrays.asList —— 定长视图
List b = Arrays.asList("x", "y");
// b.add("z"); // ❌ 抛 UnsupportedOperationException
// 但 b.set(0, "z") 可以!—— 它是"长度固定的 List",不是不可变
// 3. List.of —— 真不可变(JDK 9+)
List c = List.of("x", "y");
// c.add("z"); c.set(0, "z"); // ❌ 全部抛 UnsupportedOperationException
```
三者本质区别:**能不能 add/remove** 和**能不能 set** 是两件事——`Arrays.asList` 定长但可改元素,`List.of` 连元素都不能改。另外 `List.of` 不允许 `null` 元素,前两者允许。
## 与 equals/hashCode 的勾连
`contains`、`remove(Object)`、`indexOf` 判断"是不是同一个元素"靠的是 `equals()`,而 `HashSet`/`HashMap` 场景还依赖 `hashCode()`——自定义类放进集合前不重写这两个方法,就会出现"明明放进去却 contains 不到"的问题。详见 [[01-Object通用方法|Object 通用方法]]。
---
⬅️ [[00-容器总览|00-容器总览]] 🏠 [[00-Java|00-Java]] ➡️ [[01-ArrayList|ArrayList]]