Java 中 LinkedList 的底层数据结构及相关分析

embedded/2025/3/20 15:25:50/

Java 中 LinkedList 的底层数据结构及相关分析

1. 概述

LinkedList 是 Java 集合框架(Java Collections Framework,JCF)中的一个双向链表实现,它位于 java.util 包下,支持 列表(List)队列(Queue) 相关操作。

LinkedList 中,元素的存储方式不同于 ArrayList,它使用 链表 结构来存储元素,因此在某些场景下比 ArrayList 具有更好的性能表现。


2. LinkedList 的底层数据结构

2.1 底层实现

LinkedList 的底层是一个 双向链表(Doubly Linked List),它的基本存储单元是 Node(内部静态类),每个节点包含:

  • 数据域 (item):存储当前节点的数据。
  • 前驱指针 (prev):指向前一个节点。
  • 后继指针 (next):指向后一个节点。

2.2 源码解析(JDK 8)

Node 内部类的实现如下:

java">private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
}

LinkedList 通过 firstlast 维护头尾节点:

java">transient Node<E> first;
transient Node<E> last;

3. LinkedList 的实现原理

3.1 添加元素

add(E e) (默认尾部添加)
  1. 创建新节点。
  2. 让新节点的 prev 指向旧的 last,并更新 last 指针。
  3. 若链表为空,则 first 也指向该节点。

示例代码:

java">public boolean add(E e) {linkLast(e);return true;
}private void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;
}
add(int index, E element) (指定位置插入)
  1. 先找到索引位置的前驱和后继节点。
  2. 让新节点的 prevnext 指向前驱和后继。
  3. 更新前驱和后继节点的指针。

3.2 删除元素

  • removeFirst():删除 first 指向的节点,调整 first 指针。
  • removeLast():删除 last 指向的节点,调整 last 指针。
  • remove(index):找到索引对应节点,调整前后指针。

示例代码(删除头节点):

java">private E unlinkFirst(Node<E> f) {final E element = f.item;final Node<E> next = f.next;f.item = null;f.next = null; // help GCfirst = next;if (next == null)last = null;elsenext.prev = null;return element;
}

3.3 查找元素

  • get(int index):通过索引访问元素。
  • contains(Object o):遍历链表检查是否包含该元素。
  • indexOf(Object o):遍历链表查找元素的索引。

get(int index) 方法会从 firstlast 开始遍历(优化访问):

java">Node<E> node(int index) {if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}
}

4. LinkedList 的应用场景

4.1 适用场景

  • 频繁插入和删除元素(避免 ArrayList 频繁扩容和移动元素)。
  • 作为队列(Queue)使用,如 Deque 结构(poll()、peek() 操作)。
  • 作为栈(Stack)使用,如 push()、pop() 操作。
  • 需要双向遍历的场景

4.2 不适用场景

  • 需要频繁随机访问的情况get(index) 需要 O(n) 时间。
  • 存储大量数据时,链表结构的额外指针占用较多内存。

5. LinkedList 的优缺点

5.1 优点

✅ 插入和删除操作效率高,时间复杂度 O(1)。
✅ 适用于 FIFO 队列和 LIFO 栈操作。
✅ 动态分配内存,避免 ArrayList 频繁扩容。

5.2 缺点

❌ 访问元素效率低,查找时间复杂度 O(n)。
❌ 额外的 prevnext 指针增加内存占用。
❌ 不适用于高并发场景(非线程安全)。


6. 替代方案

需求适用数据结构
频繁插入、删除LinkedList
频繁随机访问ArrayList
线程安全的队列ConcurrentLinkedQueue
线程安全的栈Stack(不推荐),Deque(推荐)
需要自动扩容ArrayList

示例:如果希望使用线程安全的队列,可以使用 ConcurrentLinkedQueue

java">Queue<Integer> queue = new ConcurrentLinkedQueue<>();
queue.add(10);
queue.add(20);
System.out.println(queue.poll()); // 输出 10

7. 总结

  • LinkedList 底层是 双向链表,适用于 频繁插入/删除,但 随机访问较慢
  • 适用于 队列(FIFO)、栈(LIFO) 相关应用。
  • 在大多数情况下,ArrayListLinkedList 更合适,除非有特殊需求。
  • 需要线程安全时,可使用 ConcurrentLinkedQueueCopyOnWriteArrayList 等。

http://www.ppmy.cn/embedded/174181.html

相关文章

Git使用规范

摘要 本文主要讲解Git 提交需遵循相应规范。Pull Request 方面&#xff0c;一个 PR 专注一件事。信息填写中&#xff0c;Title 分仅含一个 commit 和多个 commit 的情况&#xff1b;Content 也有要求。还有其它规范&#xff0c;如连接 issue&#xff0c;pr 完成后要妥善处理&…

设计模式(创建型)-抽象工厂模式

摘要 在软件开发的复杂世界中,设计模式作为解决常见问题的最佳实践方案,一直扮演着至关重要的角色。抽象工厂模式,作为一种强大的创建型设计模式,在处理创建一系列或相关依赖对象的场景时,展现出了独特的优势和灵活性。它通过提供一个创建对象的接口,让开发者能够在不指定…

宝石PDF,全新 PC 版本,全部免费

宝石PDF已经运行 3 年时间&#xff0c;有客户端&#xff0c;小程序&#xff0c;一直未上 PC 版本&#xff0c;随着客户端功能升级的不及时&#xff0c;很多用户建议上 PC 版本。但是飞哥一直忙&#xff0c;这不终于给上了。 同时系统的名称也从 “PDF云转换”改为“宝石PDF”&…

创新实训项目初始化——gitee的使用

创新实训项目管理采用gitee&#xff0c;写下这篇博客熟悉gitee进行项目创建和版本同步 一、gitee概述 Gitee 是一个基于 Git 的代码托管平台&#xff0c;与 GitHub 类似&#xff0c;Gitee 提供了丰富的功能&#xff0c;比如代码仓库的创建、分支管理、代码审查等。 二、gite…

神经网络中层与层之间的关联

目录 1. 层与层之间的核心关联&#xff1a;数据流动与参数传递 1.1 数据流动&#xff08;Forward Propagation&#xff09; 1.2 参数传递&#xff08;Backward Propagation&#xff09; 2. 常见层与层之间的关联模式 2.1 典型全连接网络&#xff08;如手写数字分类&#xf…

攻克 PDF 发票打印难题,提升财务效率

在财务日常工作里&#xff0c;处理 PDF 格式的数电发票常常让人头疼&#xff0c;特别是合并打印环节&#xff0c;操作繁杂琐碎。别烦恼&#xff0c;今天给大家推荐一款超实用的工具——电子发票专用批量打印工具&#xff0c;专为解决 PDF 数电发票的合并打印难题而生&#xff0…

将数据添加到 Couchbase 的 Analytics(分析)服务

要将数据添加到 Couchbase 的 Analytics&#xff08;分析&#xff09;服务中&#xff0c;您需要按照以下步骤进行操作。Couchbase Analytics 服务允许您在不影响事务性工作负载的情况下&#xff0c;对大量数据执行复杂的实时分析查询。 步骤 1&#xff1a;确保 Couchbase Analy…

脚本一键式启动Nginx、Mysql、Redis

此脚本包含拉取镜像、数据卷挂载、容器启动三大部分&#xff0c;可一键式安装三大环境 新建一个depoy.sh文件在服务器上&#xff0c;然后复制以下内容。 给脚本文件添加执行权限 chmod x depoy.sh # 文件的当前目录下 如果需要修改数据库MYSQL密码和Reids密码 MYSQL_ROO…