Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

    • Java集合概述
    • ArrayList
    • LinkedList
      • 1. 核心特点
      • 2. 双向链表结构
      • 3. 作为 List 使用
      • 4. 查找元素
      • 5. 插入与删除
      • 6. 作为 Queue 使用
      • 7. 作为 Deque 使用
      • 8. LinkedList 与 ArrayDeque
      • 9. 性能误区
        • 9.1 “LinkedList 增删一定比 ArrayList 快”
        • 9.2 “链表不需要扩容,所以一定更省内存”
        • 9.3 “LinkedList 适合大量遍历”
      • 10. 适用场景
      • Tips 快问快答
    • HashMap
    • LinkedHashMap
    • HashSet
    • TreeMap
    • Queue&Deque
    • 迭代器与遍历机制
    • Collections工具类
    • 集合排序与比较器
    • 集合选型与常见问题
  • Java并发

  • Java IO

  • JVM

目录

LinkedList

LinkedList 是基于双向链表实现的集合类,同时实现了 List、Deque 和 Queue 接口。它既可以当普通列表使用,也可以当队列、双端队列、栈使用。

但在真实业务里,LinkedList 远没有新手想象中那么常用。它的优势主要在头尾节点操作和已定位节点的插入删除;如果需要按索引访问或大量遍历,通常不如 ArrayList。

# 1. 核心特点

特点 说明
底层结构 双向链表
有序 按链表节点顺序保存
可重复 允许重复元素
允许 null 可以存多个 null
随机访问慢 get(index) 需要遍历
头尾操作快 addFirst、addLast、removeFirst、removeLast 是 O(1)
非线程安全 多线程写入需要额外同步

# 2. 双向链表结构

每个节点保存元素,以及前驱、后继引用。

LinkedList
┌──────────────┐
│ first ───┐   │
│ last  ───────┼─────────────┐
│ size = 3     │             │
└──────────────┘             │
             │               │
             ▼               ▼
null <- [A] <-> [B] <-> [C] -> null

节点结构:

Node
├─ item
├─ prev
└─ next

因为每个元素都需要一个节点对象,且节点包含前后指针,所以 LinkedList 的内存开销通常高于 ArrayList。

# 3. 作为 List 使用

List<String> list = new LinkedList<>();
list.add("A");
list.add("B");
list.add(1, "X");

按索引插入时,LinkedList 需要先找到目标位置:

add(index, value)
  │
  ▼
判断 index 在前半段还是后半段
  │
  ├─ 前半段:从 first 往后找
  └─ 后半段:从 last 往前找
  │
  ▼
找到节点后修改指针

所以 list.add(index, value) 不是纯 O(1),整体通常是 O(n)。

# 4. 查找元素

String value = list.get(1000);

查找流程:

index &lt; size / 2 ?
  │
  ├─ 是:从 first 开始 next 遍历
  └─ 否:从 last 开始 prev 遍历

虽然做了前后半区优化,但本质还是链表遍历,时间复杂度 O(n)。

不要这样遍历 LinkedList:

for (int i = 0; i < list.size(); i++) {
    process(list.get(i));
}

这会让每次 get(i) 都重新遍历,整体可能退化为 O(n²)。

推荐:

for (String value : list) {
    process(value);
}

# 5. 插入与删除

头部插入:

list.addFirst("A");
原链表:
[B] &lt;-> [C]

addFirst(A):
[A] &lt;-> [B] &lt;-> [C]

尾部插入:

list.addLast("D");

删除头尾:

list.removeFirst();
list.removeLast();

头尾操作只需要修改少量引用,是 O(1)。但按值删除仍然需要遍历查找:

list.remove("A"); // O(n)

# 6. 作为 Queue 使用

LinkedList 实现了 Queue。

Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");

System.out.println(queue.poll()); // A

队列语义:

offer -> [A, B, C] -> poll
          head tail

方法对比:

操作 抛异常方法 返回特殊值方法
入队 add offer
出队 remove poll
查看队首 element peek

业务代码通常优先用 offer、poll、peek,避免空队列时抛异常。

# 7. 作为 Deque 使用

Deque 支持两端操作。

Deque<String> deque = new LinkedList<>();
deque.offerFirst("A");
deque.offerLast("B");
deque.pollFirst();
deque.pollLast();

双端结构:

offerFirst              offerLast
    │                      │
    ▼                      ▼
[ head ] &lt;-> ... &lt;-> [ tail ]
    ▲                      ▲
pollFirst              pollLast

不过如果只是做栈或队列,通常更推荐 ArrayDeque,因为数组结构更紧凑,缓存友好。

# 8. LinkedList 与 ArrayDeque

对比项 LinkedList ArrayDeque
底层结构 双向链表 循环数组
内存占用 高,每个节点有指针 较低
头尾操作 O(1) 均摊 O(1)
随机访问 支持但慢 不支持
是否允许 null 允许 不允许
队列/栈推荐度 一般 更推荐

栈场景:

Deque<String> stack = new ArrayDeque<>();
stack.push("A");
stack.push("B");
System.out.println(stack.pop());

不要优先使用 Stack,它是早期遗留类,继承自 Vector,同步模型和 API 都不够现代。

# 9. 性能误区

# 9.1 “LinkedList 增删一定比 ArrayList 快”

不一定。中间插入删除分两步:

找到位置 O(n)
修改指针 O(1)

如果位置是通过索引给出的,定位成本仍然很高。

# 9.2 “链表不需要扩容,所以一定更省内存”

不一定。链表每个元素都要一个节点对象,还要保存 prev 和 next,对象数量多,内存开销和 GC 压力可能更大。

# 9.3 “LinkedList 适合大量遍历”

通常不如 ArrayList。数组连续存储,CPU 缓存命中更好;链表节点分散,遍历时指针跳转更多。

# 10. 适用场景

适合:

  • 需要频繁从头尾插入删除。
  • 已经持有迭代器位置,需要在附近插入删除。
  • 需要一个允许 null 的 Deque。

不适合:

  • 大量随机访问。
  • 大量按索引遍历。
  • 对内存占用敏感。
  • 普通业务列表。

普通列表优先 ArrayList,队列和栈优先 ArrayDeque。

# Tips 快问快答

Q:LinkedList 底层是什么? A:双向链表,每个节点保存元素、前驱和后继引用。

Q:LinkedList 的 get(index) 是 O(1) 吗? A:不是,需要从头或尾遍历,时间复杂度 O(n)。

Q:为什么 LinkedList 按索引遍历很慢? A:每次 get(i) 都要重新找节点,循环里使用可能变成 O(n²)。

Q:LinkedList 插入删除一定快吗? A:只有已定位节点或头尾操作快;如果要先按索引查找,整体仍可能是 O(n)。

Q:LinkedList 能当队列用吗? A:能,它实现了 Queue 和 Deque。

Q:栈应该用 LinkedList 还是 Stack? A:通常用 ArrayDeque,不推荐老的 Stack。

Q:LinkedList 允许 null 吗? A:允许。

Q:LinkedList 线程安全吗? A:不安全,需要外部同步或使用并发集合。

Q:为什么 ArrayDeque 经常比 LinkedList 更适合队列? A:它基于数组,内存更紧凑,缓存友好,头尾操作也很快。

Q:普通业务列表什么时候选 LinkedList? A:很少。只有明确依赖链表头尾操作或迭代器插入删除特性时再考虑。

上次更新: 2026/06/24, 16:37:44
ArrayList
HashMap

← ArrayList HashMap→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式