news 2026/2/16 14:18:20

数据结构(Java版)第八期:LinkedList与链表(三)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
数据结构(Java版)第八期:LinkedList与链表(三)

数据结构第八期:LinkedList 与链表(Java 版)

这是 Java 中最常被问到的数据结构之一,也是面试、笔试、日常开发中最容易踩坑的地方。

下面从原理 → 源码 → 常见操作 → 面试高频题 → 实际使用建议完整梳理一遍。

1. LinkedList 在 Java 中的真实身份

publicclassLinkedList<E>extendsAbstractSequentialList<E>implementsList<E>,Deque<E>,Cloneable,java.io.Serializable

一句话总结:
LinkedList 同时实现了 List 和 Deque 接口,所以它既是“双向链表”,也是“双端队列”

最关键的两点:

  • 底层是双向链表(doubly-linked list)
  • 没有像 ArrayList 那样的连续数组存储

2. 核心内部结构(JDK 8/11/17/21 一致)

privatestaticclassNode<E>{Eitem;// 元素本身Node<E>next;// 后继指针Node<E>prev;// 前驱指针}

三个重要成员变量:

transientintsize=0;// 元素个数transientNode<E>first;// 头节点(first)transientNode<E>last;// 尾节点(last)

最经典的图示(双向链表)

null ← prev [prev | item | next] ↔ [prev | item | next] ↔ [prev | item | next] next → null ↑ first ↑ last

3. 常用操作的时间复杂度(面试必背)

操作时间复杂度说明
get(index)O(n)从头/尾选近的一端开始遍历
set(index, element)O(n)同上,需要找到第 index 个节点
addFirst / addLastO(1)直接操作 first/last 指针
add(index, element)O(n)找到位置 + 修改指针(最坏 O(n))
removeFirst / removeLastO(1)直接操作 first/last
remove(Object o)O(n)需要线性查找 + 修改指针
remove(index)O(n)找到节点 + 修改前后指针
contains(Object o)O(n)线性查找
size() / isEmpty()O(1)直接返回 size 字段
iterator() / listIterator()O(1)返回链表迭代器(支持双向遍历)

一句话总结
凡是涉及“按索引操作”的几乎都是 O(n),凡是“头尾操作”的都是 O(1)

4.LinkedList 作为 Deque(双端队列)的常用方法

LinkedList 实现了 Deque 接口,所以可以用它当队列双端队列用。

场景首选方法(推荐)等价方法(不推荐抛异常版)说明
入队(尾)offerLast(e) / addLast(e)add(e)尾插
出队(头)pollFirst()removeFirst()头出,空返回 null
入栈(头)push(e)addFirst(e)头插(栈顶)
出栈(头)pop()removeFirst()头出(栈顶)
取头peekFirst()getFirst()看头元素,不删除
取尾peekLast()getLast()看尾元素,不删除

面试最爱问的写法对比

// 当栈用(LIFO)LinkedList<Integer>stack=newLinkedList<>();stack.push(1);// 入栈stack.push(2);stack.pop();// 出栈 → 2
// 当队列用(FIFO)LinkedList<Integer>queue=newLinkedList<>();queue.offer(1);// 入队queue.offer(2);queue.poll();// 出队 → 1

5. 源码中最容易被问到的几个点

  1. addFirst / addLast 的实现(O(1))
publicvoidaddFirst(Ee){linkFirst(e);}privatevoidlinkFirst(Ee){finalNode<E>f=first;finalNode<E>newNode=newNode<>(null,e,f);first=newNode;if(f==null)last=newNode;elsef.prev=newNode;size++;modCount++;}
  1. get(int index) 为何慢(O(n))
publicEget(intindex){checkElementIndex(index);returnnode(index).item;}Node<E>node(intindex){// assert isElementIndex(index);if(index<(size>>1)){// 前半段从头开始找Node<E>x=first;for(inti=0;i<index;i++)x=x.next;returnx;}else{// 后半段从尾开始找(关键优化!)Node<E>x=last;for(inti=size-1;i>index;i--)x=x.prev;returnx;}}
  1. 为什么 LinkedList 实现了 RandomAccess 接口?

答案它其实没有实现 RandomAccess
(ArrayList 实现了,LinkedList 没有)

publicclassArrayList<E>...implementsRandomAccess...publicclassLinkedList<E>...// 没有 implements RandomAccess

这也是为什么List遍历时推荐用for-eachiterator,而不是get(i)循环的原因。

6. 面试高频题 TOP 10(带答案)

  1. LinkedList 是线程安全的吗?
    否。所有方法都没有 synchronized。

  2. LinkedList 和 ArrayList 的区别?(必问)

项目ArrayListLinkedList
底层结构动态数组双向链表
随机访问O(1)O(n)
插入/删除(头尾)O(n)(需移动元素)O(1)
插入/删除(中间)O(n)O(n)(查找)+O(1)(修改指针)
内存开销较小(连续)较大(每个节点有 prev/next)
适用场景读多写少、频繁随机访问频繁头尾增删、队列/栈
  1. LinkedList 可以当栈和队列用吗?怎么用?
    可以。推荐用 push/pop 当栈,offer/poll 当队列。

  2. 为什么 LinkedList 没有 capacity(容量)概念?
    因为是链表,不需要预分配空间。

  3. Iterator 和 ListIterator 的区别?
    LinkedList 的 iterator() 是单向的,listIterator() 是双向的,支持 add/set/remove。

  4. modCount 有什么作用?
    快速失败机制(fail-fast)。结构修改时 modCount++,迭代器发现 modCount 变化就抛 ConcurrentModificationException。

  5. ConcurrentLinkedQueue 和 LinkedList 的区别?
    前者是线程安全的无界队列(CAS),后者非线程安全。

  6. 为什么不建议用 LinkedList 做大数据量的随机访问?
    每次 get(i) 都要从头/尾遍历,时间复杂度 O(n),n 很大时很慢。

  7. LinkedList 的 subList() 返回的是什么?
    SubList 内部类,是原链表的视图,修改会影响原链表(非深拷贝)。

  8. 实际项目中什么时候选 LinkedList?

7. 2026 年真实使用建议

需要我手写一个双向链表的完整实现(不依赖 LinkedList)吗?
或者想看 LinkedList 在 LeetCode 哪些题中是最佳解?
随时告诉我~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/13 17:53:49

【大数据毕设全套源码+文档】基于Django+Hadoop的热点新闻分析系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/2/12 1:33:08

如何用BERT做中文语义填空?保姆级部署教程一文详解

如何用BERT做中文语义填空&#xff1f;保姆级部署教程一文详解 1. 引言&#xff1a;让AI帮你“猜”中文语境中的缺失词 你有没有遇到过一句话读到一半&#xff0c;突然卡壳&#xff0c;不知道该接什么词&#xff1f;或者写文章时想不起某个成语的准确表达&#xff1f;现在&am…

作者头像 李华
网站建设 2026/2/8 2:06:49

CAM++服务器部署全流程:从镜像到API调用详解

CAM服务器部署全流程&#xff1a;从镜像到API调用详解 1. 引言&#xff1a;为什么你需要一个说话人识别系统&#xff1f; 你有没有遇到过这样的场景&#xff1a;一段录音里有多个声音&#xff0c;你想知道其中两段是不是同一个人说的&#xff1f;或者你正在做身份验证系统&am…

作者头像 李华
网站建设 2026/2/15 5:21:15

Qwen3-0.6B知识库问答实战:RAG架构集成详细步骤

Qwen3-0.6B知识库问答实战&#xff1a;RAG架构集成详细步骤 1. 为什么选Qwen3-0.6B做知识库问答&#xff1f; 很多人一听到“大模型”就默认要上几十GB显存、跑7B甚至更大参数的模型。但现实是&#xff1a;很多企业内部知识库场景——比如产品文档检索、客服FAQ响应、员工培训…

作者头像 李华
网站建设 2026/2/16 14:09:23

RTX 4090D用户福音!Z-Image-Turbo高效绘图实测

RTX 4090D用户福音&#xff01;Z-Image-Turbo高效绘图实测 1. 为什么RTX 4090D用户该关注Z-Image-Turbo&#xff1f; 你是不是也经历过这样的时刻&#xff1a;刚入手RTX 4090D&#xff0c;显存堆到24GB&#xff0c;却卡在文生图模型的加载环节——等下载、等解压、等编译&…

作者头像 李华