【集合框架LinkedList底层添加元素机制】

在 Java 集合框架中,LinkedListArrayList 是两种截然不同的线性表实现。如果说 ArrayList 像一个可以伸缩的“盒子阵列”,那么 LinkedList 就像一条由“节点”串联而成的“双向链条”。

今天,我们将深入 LinkedList 的源码,一步步剖析它作为双向链表的精妙设计。通过这篇解析,你将彻底明白 LinkedList 是如何通过 firstlast 指针,高效地管理元素的。


一、LinkedList 的诞生:空链的起点

当我们执行 new LinkedList<>() 时,LinkedList 在底层做了什么?

// 代码块
LinkedList<String> list = new LinkedList<>();

核心真相:此时,LinkedList 并没有创建任何节点。它只初始化了两个至关重要的指针(引用)

  1. first:指向链表的头节点(第一个节点)。
  2. last:指向链表的尾节点(最后一个节点)。

在创建之初,链表为空,因此 firstlast 都被初始化为 null

// 代码块
// LinkedList 源码中的定义
transient Node<E> first;
transient Node<E> last;


二、成长的第一步:添加第一个元素

当我们调用 list.add("Hello") 时,发生了什么?

  1. 创建新节点LinkedList 会创建一个全新的 Node 对象。这个节点的结构非常简单,包含三部分:
    • item:存储元素 "Hello"
    • next:指向下一个节点的引用。
    • prev:指向前一个节点的引用。
  2. 初始化节点:由于这是第一个节点,它的 prev 和 next 都指向 null
  3. 更新指针first 和 last 这两个指针,都指向这个新创建的节点。因为此时,这个节点既是头节点,也是尾节点。
// 代码块
// Node 类的定义 (简化)
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 的内部结构如下图所示:


三、链的延伸:添加第二个元素

当我们调用 list.add("World") 时,链表开始延伸。

  1. 创建新节点:创建一个新的 Node 对象,存储元素 "World"
  2. 建立连接
    • 前向连接:第一个节点(当前的 last)的 next 指针,将指向这个新节点。
    • 后向连接:新节点的 prev 指针,将指向第一个节点。
  3. 更新尾指针last 指针不再指向第一个节点,而是更新为指向这个新创建的节点first 指针保持不变,仍然指向第一个节点。

此时,链表的结构变成了:

first -> [item: "Hello", prev: null, next: ->] <-> [item: "World", prev: <-, next: null] <- last

四、双向链表的魅力:高效的操作

LinkedList 的双向链表结构赋予了它独特的优势:

1. 头尾操作的极致效率

  • addFirst() / addLast():由于 first 和 last 指针的存在,向链表头部或尾部添加元素的时间复杂度都是 O(1)
  • removeFirst() / removeLast():同理,删除头尾元素也是 O(1)

2. 中间插入/删除的“局部性”

  • 在链表中间插入或删除元素,虽然需要先通过遍历找到位置(O(n)),但一旦找到,实际的插入/删除操作本身是 O(1) 的,因为它只需要修改相邻节点的指针,而不需要像 ArrayList 那样移动大量元素。

3. 内存的“按需分配”

  • 与 ArrayList 预先分配数组不同,LinkedList 的每个节点都是在需要时才创建,内存使用更“灵活”,但每个节点有额外的 prev 和 next 引用开销。

最终效果:


五、总结:LinkedList 的设计哲学

通过这次源码级的剖析,我们可以总结出 LinkedList 的核心工作原理:

阶段关键动作指针变化
创建初始化 first 和 last 指针first = nulllast = null
首次添加创建节点,first 和 last 都指向它first -> Node1last -> Node1
后续添加创建新节点,修改相邻节点指针,更新 lastNode1.next -> Node2Node2.prev -> Node1last -> Node2

LinkedList 的“动态”源于其节点化指针链接的设计。它用 firstlast 两个指针高效地管理链表的两端,用 prevnext 构建了双向的连接,使得头尾操作异常迅速。

何时选择 LinkedList

  • 频繁在列表的头部或尾部进行插入/删除操作。
  • 需要实现栈(Stack) 或 队列(Queue) 的数据结构(LinkedList 实现了 Deque 接口)。

何时避免 LinkedList

  • 需要频繁进行随机访问get(index)),因为需要从头或尾遍历。
  • 内存非常紧张,因为每个节点有额外的引用开销。

理解了 LinkedList 的双向链表本质,你就能在 ArrayListLinkedList 之间做出更明智的选择。

希望这篇解析能帮你彻底掌握 LinkedList 的源码精髓!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/919629.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/919629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《P2700 逐个击破》

题目背景三大战役的平津战场上&#xff0c;傅作义集团在以北平、天津为中心&#xff0c;东起唐山西至张家口的铁路线上摆起了一字长蛇阵&#xff0c;并企图在溃败时从海上南逃或向西逃窜。为了就地歼敌不让其逃走&#xff0c;指挥官制定了先切断敌人东西两头退路然后再逐个歼灭…

C6.0:晶体管放大器的原理与应用(基极偏置篇)

将晶体管Q点偏置在负载线中点附近后&#xff0c;如果将一个小的交流信号耦合到基极上&#xff0c;便会产生一个交流的集电极电压&#xff0c;交流集电极电压与交流基极电压波形相似&#xff0c;但是幅度要大了很多&#xff0c;即交流集电极电压是对交流基极电压的放大。本篇学习…

Oracle: cannot decrease column length because some value is too big

1.背景今天项目上查不到数据,查库发现默认20位的字段被改为了200,用的还是char类型&#xff0c;填充了一堆空格 2.知识LENGTH() 函数用于计算字符串字段 长度TRIM() 函数用于去除字符串字段 column 前后的空格&#xff08;默认&#xff09;或指定字符&#xff1a;SUBSTR() 用于…

Elasticsearch 写入全链路:从单机到集群

0. 先把术语摆正 Index&#xff08;索引&#xff09;&#xff1a;逻辑数据集合&#xff0c;≈ MySQL 的库。Document&#xff08;文档&#xff09;&#xff1a;一条 JSON 数据&#xff0c;≈ MySQL 的行。Field&#xff08;字段&#xff09;&#xff1a;文档里的键值&#xff0…

Java多线程编程——基础篇

目录 前言 一、进程与线程 1、进程 2、线程 二、并发与并行 1、并发 2、并行 三、线程调度 1、CPU时间片 2、调度方式 ①时间片轮转 ②抢占式调度 四、线程实现方式 1、继承 Thread 类 Thread的多种构造函数&#xff1a; 2、实现 Runnable 接口 五、线程的核心方法 1、start() …

阿里云的centos8 服务器安装MySQL 8.0

在 CentOS 8 上安装 MySQL 8.0 可以通过添加 MySQL 官方 YUM 仓库并使用 dnf 命令安装。以下是具体步骤&#xff1a; 步骤如下&#xff1a; 下载并添加 MySQL 官方 YUM 仓库 运行以下命令下载 MySQL 8.0 的 YUM 仓库配置文件&#xff1a; sudo dnf install https://dev.mysql.…

【运维进阶】Linux 正则表达式

Linux 正则表达式定义&#xff1a;正则表达式是一种pattern&#xff08;模式&#xff09;&#xff0c;用于与待搜索字符串匹配&#xff0c;以查找一个或多个目标字符串。组成&#xff1a;自成体系&#xff0c;由两类字符构成普通字符&#xff1a;未被显式指定为元字符的所有可打…

STM32输入捕获相位差测量技术详解(基于TIM1复位模式)

本文将深入解析基于STM32定时器输入捕获功能的方波相位差测量技术&#xff0c;通过复位模式实现高精度相位检测。以下是完整的代码实现与详细原理分析。一、相位差测量原理相位差测量基于两个同频方波信号下降沿时间差计算。核心原理&#xff1a;​复位模式​&#xff1a;将TIM…

什么是股指期货可转移阿尔法策略?

阿尔法&#xff08;Alpha&#xff09;是投资领域的一个术语&#xff0c;用来衡量投资组合的超额收益。简单来说&#xff0c;阿尔法就是你在市场上赚的比平均水平多出来的那部分钱。比如&#xff0c;市场平均收益率是5%&#xff0c;但你的投资组合收益率是10%&#xff0c;那你的…

AXI GPIO S——ZYNQ学习笔记10

AXI GPIO 同意通道混合输入输出中断控制#KEY set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[0]}] set_property PACKAGE_PIN J13 [get_ports {AXI_GPIO_KEY_tri_io[0]}] set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[1]}] set_pro…

如何通过传感器选型优化,为设备寿命 “续航”?

在当今竞争激烈的工业领域&#xff0c;企业就像在一场没有硝烟的战争中角逐&#xff0c;设备便是企业的“秘密武器”。设备的使用寿命&#xff0c;如同武器的耐用程度&#xff0c;直接决定了企业在生产战场上的“战斗力”。延长设备寿命&#xff0c;已然成为众多企业降低生产成…

WebSocket连接的例子

// 初始化WebSocket连接 const initWebSocket () > {console.log("初始化链接中...")const websocketUrl ws://61.54.84.16:9090/;// WebSocket服务器地址websocket new WebSocket(websocketUrl)//使用真实的webscket// websocket new MockWebSocket(websocket…

c++之指针和引用

一 使用场景 C++ 什么时候使用指针?什么时候使用引用?什么时候应该按值传递?_引用什么时候用比较好-CSDN博客 只使用传递过来的值,而不对值进行修改 需要修改传递过来的值 内置数据类型 按值传递(小型结构) 指针传递 数组 指针传递 指针传递 结构 指针或引用(较大的结构…

pytorch学习笔记-模型训练、利用GPU加速训练(两种方法)、使用模型完成任务

应该算是完结啦~再次感谢土堆老师&#xff01; 模型训练 模型训练基本可以分为以下几个步骤按序执行&#xff1a; 引入数据集-使用dataloader加载数据集-建立模型-设置损失函数-设置优化器-进行训练-训练中计算损失&#xff0c;并使用优化器更新参数-模型测试-模型存储 习惯上会…

深度卷积神经网络AlexNet

在提出LeNet后卷积神经网络在计算机视觉和机器学习领域中报有名气&#xff0c;但是卷积神经网络并没有主导这些领域&#xff0c;因为LeNet在小数据集上取得了很好的效果&#xff0c;在更大&#xff0c;更真实的数据集上训练卷积神经网络的性能 和可行性有待研究&#xff0c;20世…

数据结构-HashSet

在 Java 编程的世界里&#xff0c;集合框架是极为重要的一部分&#xff0c;而 HashSet 作为 Set 接口的典型实现类&#xff0c;在处理不允许重复元素的场景中频繁亮相。今天&#xff0c;我们就一同深入探究 HashSet&#xff0c;梳理它的特点、常用方法&#xff0c;以及和其他相…

心意行药号 · 慈心方的八种用法

心意行药号 慈心方的八种用法慈心方是心意行药号589个珍贵秘方中的一个养生茶方&#xff0c;配伍比例科学严谨&#xff0c;君臣佐使堪称经典&#xff0c;自古就有“小小慈心方&#xff0c;转动大乾坤”之说。自清代光绪年间传承至今&#xff0c;慈心方受益者逾百万计&#xff…

Spring面试宝典:Spring IOC的执行流程解析

在准备Spring框架的面试时&#xff0c;“Spring IOC的工作流程是什么&#xff1f;” 是一个非常经典的问题。虽然网上有很多详细的教程&#xff0c;但它们往往过于复杂&#xff0c;对于没有深入研究过源码的人来说理解起来确实有些困难。今天我们就来简化这个概念&#xff0c;从…

学习日志39 python

1 fromkeys()函数是什么在 Python 中&#xff0c;fromkeys() 是字典&#xff08;dict&#xff09;的一个类方法&#xff0c;用于创建一个新字典。它的作用是&#xff1a;根据指定的可迭代对象&#xff08;如列表、元组等&#xff09;中的元素作为键&#xff08;key&#xff09;…

SpringBoot + MyBatis-Plus 使用 listObjs 报 ClassCastException 的原因与解决办法

在项目中我们经常会遇到这种需求&#xff1a; 根据一组 ID 查询数据库&#xff0c;并返回指定字段列表。 我在写代码的时候&#xff0c;遇到了一个典型的坑&#xff0c;分享出来给大家。一、问题背景我的代码是这样写的&#xff08;查询项目表的负责人信息&#xff09;&#xf…