LinkedList源码

JavaSE基础知识(二十一)--Java集合(容器)之类LinkedList的源码分析(已修改) Java SE 是什么,包括哪些内容(二十一)? 本文内容参考自Java8标准 顺序访问列表的一个常用实现类: LinkedList 类声明: public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Clonea... 阅读详情

1: 结构

 

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
  • LinkedList是一个实现了List接口和Deque接口的双端链表
  • LinkedList底层的链表结构使它支持高效的插入和删除操作,
  • 另外它实现了Deque接口,使得LinkedList类也具有队列的特性;
  • LinkedList不是线程安全的,如果想使LinkedList变成线程安全的,可以调用静态类Collections类中的synchronizedList方法

2:属性

transient int size = 0; //节点数量
transient Node<E> first; // 第一个节点
transient Node<E> last;// 最后一个节点


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;
    }
}

3:构造方法

(1)LinkedList(): 构造一个空列表

public LinkedList() {
}

(2)构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序

public LinkedList(Collection<? extends E> c) {
    this();
    addAll(c);
}

4:add(E e):将指定的元素追加到此列表的末尾

public boolean add(E e) {
    linkLast(e);
    return true;
}

void linkLast(E e) {
    //记录当前末尾节点
    final Node<E> l = last;      
    //产生一个新的节点 该节点的前驱节点是之前的last,后继节点是null
    final Node<E> newNode = new Node<>(l, e, null);
     //将last 尾指针指向新的节点      
    last = newNode;   
    if (l == null)
        first = newNode;    //链表中没有节点, 头指针指向新节点
    else
        l.next = newNode;    // 当前last的next指向新节点
    size++;//更新节点数量
    modCount++;
}

步骤:

1:记录当前末尾节点,用添加元素产生一个新的节点

2:将last指针指向新的尾节点

3:情况1:如果之前的尾节点为空,表明链表中没有元素,头指针first指向新节点

4:情况2:如果之前的链表不为空,旧的尾节点的next指针指向新的尾节点

 

5:add(int index,E element):指定位置插入指定元素

public void add(int index, E element) {
    checkPositionIndex(index);// 校验索引位置

    if (index == size)  // 在最后插入
        linkLast(element);
    else  
        linkBefore(element, node(index));// 在索引位置之前插入
}

// 折半查找,返回指定索引位置的节点
//(1)首先确定index的位置,,是靠近first还是靠近last
//(2)靠近first就从头开始查,否则就从尾部开始
Node<E> node(int index) {
    // assert isElementIndex(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;
    }
}

void linkBefore(E e, Node<E> succ) {// succ是之前index位置上的节点,将e插到succ节点前面
    // assert succ != null;
    final Node<E> pred = succ.prev; // 拿到succ节点的prev节点
    //构造新节点,新插入节点的前驱节点是succ的前一个位置的节点,后继节点是succ节点
    final Node<E> newNode = new Node<>(pred, e, succ);  
    succ.prev = newNode;// 将succ节点的prev属性设置为newNode
    if (pred == null) 
        first = newNode;   // 之前只有一个节点
    else
        pred.next = newNode; //将pred节点的next属性设为newNode
    size++;
    modCount++;
}

 

6:get(int index):返回此列表中指定位置的元素

public E get(int index) {
    checkElementIndex(index); // 检查index是否越界
    return node(index).item; // 根据index,调用node方法寻找目标节点,返回目标节点的item
}

7:删除节点

(1)删除指定位置

public E remove(int index) {
    checkElementIndex(index);  //检查index    index >= 0 && index < size;
    return unlink(node(index));
}

(2)删除指定值的节点

public boolean remove(Object o) {
    //判断删除的元素是否是null
    if (o == null) {
        for (Node<E> x = first; x != null; x = x.next) {
            if (x.item == null) {
                unlink(x);
                return true;
            }
        }
    } else {
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item)) {
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

重点方法:unlink(Node<E> e)

E unlink(Node<E> x) {// 移除链表上的x节点
    // assert x != null;
    final E element = x.item; // x节点的值
    final Node<E> next = x.next;// x节点的下一个节点
    final Node<E> prev = x.prev;// x节点的上一个节点

 
    if (prev == null) {//如果prev为空,则代表x节点为头节点,删除的是第一个节点,first向后移动
        first = next;
    } else {// x不为头节点
        prev.next = next; //将prev节点的next书香指向x节点的next属性
        x.prev = null;  // 将x节点prev置空
    }

    if (next == null) { // 如果next为空,则代表x节点为尾节点,则将last指向prev即可
        last = prev;
    } else {// x不是尾节点
        next.prev = prev; // 将next节点的prev属性指向x节点的prev属性
        x.next = null;// 该节点next置空
    }

    x.item = null;  // 将x的值清空,以便垃圾回收器回收对象
    size--; // 节点个数减1
    modCount++;
    return element;
}

 删除步骤:

(1)获取到需要删除元素当前的值,指向它前一个节点的引用,以及指向它后一个节点的引用

(2)判断删除的是否为第一个节点,若是则first向后移动,若不是则将当前节点的前一个节点next指向当前节点的后一个节点

(3)判断删除的是否为最后一个节点,若是则last向前移动,若不是则将当前节点的后一个节点的prev指向当前节点的前一个节点

(4)将当前节点的值设置为null

(5)size减少并返回删除结点的值

8:clear():清除链表的所有节点

public void clear() {
    for (Node<E> x = first; x != null; ) { // 从头节点开始遍历将所有节点的属性清空
        Node<E> next = x.next; // 记录后继节点
        x.item = null;  // 清空
        x.next = null;
        x.prev = null;
        x = next;
    }
    first = last = null;// 将头节点和尾节点设为null
    size = 0;
    modCount++;
}

9: ArrayList与LinkedList比较

相同点:

  • 接口实现:都实现了List接口,都是线性列表的实现
  • 都是线程不安全的
  • 实现线程安全使用工具类Collections.synchronizedList(new ArrayList())方法。

区别:

  • 底层实现:ArrayList内部是数组实现,LinkedList内部实现是双向链表
  • 接口实现:ArrayList实现了RandomAccess可以支持随机元素访问,LinkerList实现了Deque可以当作队列使用
  • 性能:ArrayList支持随机元素访问,LinkedList新增,删除快

 

LinkedList 源码分析 从这个方法的源码可以看出,该方法通过比较索引值与链表 size 的一半大小来确定从链表头还是尾开始遍历。如果索引值小于 size 的一半,就从链表头开始遍历,反之从链表尾开始遍历。这样可以在较短的时间内找到目标节点,充分利用了双向链表的特性来提高效率。仅仅在头尾插入或者删除元素的时候时间复杂度近似 O(1),其他情况增删元素的平均时间复杂度都是 O(n)底层数据结构是链表,内存地址不连续,只能通过指针来定位,不支持随机快速访问,所以不能实现。来代替,并且,性能通常会更好!的遍历的核心就是它的迭代器的实现。 阅读详情

相关推荐

【HSPiP应用指南】从理论到实践:如何利用汉森溶解度参数优化配方设计

本文深入解析了汉森溶解度参数(HSP)理论及其在配方设计中的核心价值,并详细介绍了如何利用HSPiP软件工具从理论走向实践。文章通过匹配溶解度参数、计算汉森距离(Ra),系统阐述了如何解决溶剂选择、颜料分散稳定性及扩散行为预测等关键问题,并结合界面气相色谱(IGC)等实验方法提升预测精度,旨在帮助配方师实现配方设计的可视化、可量化与高效优化。

weixin_29305313的博客 1650

LinkedList源码解析

简介 一个非同步的双链表集合,双链表的数据结构示意图如下: 在LinkedList内部包含一个Node的内部类,这个内部类是每一个元素的信息。 private static class Node<E> { E item; Node<E> next; Node<E> prev; } 从Node的代码中可以非常清楚的看到,每个元素中包含每个元素、以及上一个元素、下一个元素的指针。 重要方法分析 link link 相关方法包括l..

lyz417的专栏 469

人工势场法三大致命缺陷?我用ROS+Gazebo做了组对比实验

本文通过ROS与Gazebo仿真实验,深入剖析了人工势场法(APF)在机器人路径规划中的三大经典问题:局部最小值、目标不可达和路径震荡。文章不仅复现了这些缺陷,还对比测试了虚拟目标点法、改进斥力场及运动平滑等主流改进方案,为工程选型提供了基于数据的实用建议。

dapp9builder的博客 219

LinkedList源码详解

文章目录1 LinkedList源码1.1 链表的概念1.1.1 单向链表1.1.2 单向循环链表1.1.3 双向链表1.1.4 双向循环链表1.2 定义1.2.1 类的属性1.2.2 Node 的静态内部类1.2.3 构造函数1.2.4 查找 - get1.2.5 添加add1.2.6 修改1.2.7 删除 1 LinkedList源码 LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明。 1.1 链表的概念 链表是由一系列非连续的节点组成的存储结构

上善若泪 899

中国1990-2021连续30年土地利用CLCD数据分享

CLCD(China Land Cover Dataset)数据集是由武汉大学黄昕老师基于Google Earth Engine上的335,709景Landsat数据制作的中国年度土地覆盖数据集。为了提高CLCD的时空一致性,还提出了一种包含时空滤波和逻辑推理的后处理方法。该数据集最大的优势在于每年30米的土地利用分类结果,且连续覆盖了30年时间。相比其他产品如GLC_FCS30、Global30、AGLC2000_2015、FROM-GLC10、ESA10、ESRI10等,CLCD在时间分辨率上更高。

qq_48539301的博客 1万+

Jetson AGX Orin 新手避坑:解决‘找不到nvidia-jetpack包’的完整修复指南

本文详细介绍了Jetson AGX Orin设备在安装JetPack开发套件时遇到的'nvidia-jetpack包缺失'问题的完整解决方案。通过分析问题根源、提供分步修复指南以及系统优化建议,帮助开发者快速解决这一常见问题,充分发挥Jetson AGX Orin的边缘计算性能。

weixin_42520909的博客 461

源码分析——LinkedList源码分析

LinkedList是一个实现了List接口和Deque接口的双端链表。LinkedList底层的链表结构使它支持高效的插入和删除操作,另外它实现了Deque接口,使得LinkedList类也具有队列的特性;LinkedList不是线程安全的,如果想使LinkedList变成线程安全的,可以调用静态类Collections类中的。

帆的博客 256

YOLOv8【第九章:模型部署篇·第2节】一文搞懂,模型剪枝与压缩技术!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏。该专栏系统复现并梳理全网各类 YOLOv8 改进与实战案例(当前已覆盖分类 / 检测 / 分割 / 追踪 / 关键点 / OBB 检测等方向),坚持持续更新 + 深度解析,质量分长期稳定在 97 分以上,可视为当前市面上 覆盖较全、更新较快、实战导向极强 的 YOLO 改进系列内容之一。

**My Coding Family** 1529

源码阅读之LinkedList

昨天阅读了ArrayList的源码,今天继续努力,将List下的LinkedList的源码也阅读一遍。相对于ArrayList的底层实现是用数组实现而言,LinkedList底层则是使用双向链表(之前版本使用的是循环双向链表)。双向链表结构如下: private static class Node<E> { E item; Node<E...

LMR的博客 9196

OpenOCD入门到精通:第 4 章 配置文件体系详解

本文深入解析OpenOCD配置文件的体系结构和工作机制。首先介绍了配置文件的搜索路径优先级和加载顺序,以及配置阶段与运行阶段的区别。然后详细分析了interface配置文件的适配器参数调优方法,包括ST-Link、CMSIS-DAP和FTDI等常见调试器的配置示例。最后重点讲解了target配置文件的核心结构,包括TAP声明、目标创建和工作区设置等关键步骤,并以stm32f1x为例展示了完整的配置流程。通过本文可以全面了解OpenOCD配置文件的分层设计理念和参数化配置方法。

从事嵌入式linux android驱动开发,拥有全栈能力 595

海康Visionmaster-全局脚本:VM 加载方案后自动执行 的方法,如何让VM在方案加载后自动执行流程?

海康Visionmaster-全局脚本:VM 加载方案后自动执行 的方法,如何让VM在方案加载后自动执行流程?

视觉人机器视觉的博客 2038

java linkedlist源码_Java 集合之LinkedList源码分析

1.介绍链表是数据结构中一种很重要的数据结构,一个链表含有一个或者多个节点,每个节点处理保存自己的信息之外还需要保存上一个节点以及下一个节点的指针信息。通过链表的表头就可以访问整个链表的信息。Java API中提供了链表的Java实现---LinkedList下。LinkedList是通过节点的连接实现链表的数据结构,向linkedList中插入或删除元素的速度是特别快,而随机访问的速度相对较慢,...

weixin_35677144的博客 240

SAP-RPT-1 深度解读:面向企业表格数据的 rapid one

摘要: SAP在TechEd 2025大会上推出面向企业结构化数据的SAP-RPT-1(Relational Pretrained Transformer),旨在通过in-context learning直接预测表格数据中的缺失值,无需传统机器学习流程。与LLM不同,RPT专为业务表格设计,支持实时预测(如交货延迟、回款风险等)。提供Small(高吞吐)、Large(高精度)和开源版本,用户可通过无代码Playground(上传CSV并用[PREDICT]标记目标列)或Python API快速验证。典型场景

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 238

LinkedList源码分析

LinkedList是一种可以在任何位置进行高效地插入和移除操作的有序序列,它是基于双向链表实现的。 1、继承结构 2、LinkedList数据结构 如上图所示,LinkedList底层使用的双向链表结构,有一个头结点和一个尾结点,双向链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作。 3、源码分析 3.1、AbstractSequ...

通往神秘的道路的专栏 3209

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Java 中 LinkedList 的底层源码

方法用于返回指定元素在链表中最后一次出现的索引,如果不存在则返回 -1。x!= null;index--;} else {x!= null;index--;return -1;该方法从链表尾部开始遍历,分别处理查找元素为null和不为null的情况,找到匹配元素时返回其索引,遍历完链表都未找到则返回 -1。通过对LinkedList底层源码的剖析,我们清楚地了解了它的结构和各种操作的实现原理。LinkedList在插入和删除元素时具有高效性,尤其是在链表中间位置进行操作时,不需要像。

2202_75481735的博客 1214

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

LinkedList源码及原理

简介 内部结构分析 LinkedList源码分析 构造方法 添加(add)方法 根据位置取数据的方法 根据对象得到索引的方法 检查链表是否包含某对象的方法: 删除(remove/pop)方法 LinkedList类常用方法测试: 简介 LinkedList是一个实现了List接口和Deque接口的双端链表。 LinkedList底层的链表结构使它支持高效的...

weixin_30267691的博客 186

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

java linkedlist源码_Java集合---LinkedList源码解析

一、源码解析1、 LinkedList类定义2、LinkedList数据结构原理3、私有属性4、构造方法5、元素添加add()及原理6、删除数据remove()7、数据获取get()8、数据复制clone()与toArray()9、遍历数据:Iterator()二、ListItr一、源码解析1、LinkedList类定义。public class LinkedListextends Abstra...

weixin_35828357的博客 323

LinkedList源码理解分析和使用

文章目录1. 基本使用方法2. LinkedList源码成员变量和内部类2.1 成员变量2.2 内部类3. LinkedList的所有源码和分析注释4. 使用LinkedList实现栈效果5. LinkedList实现队列效果 1. 基本使用方法 import java.util.LinkedList; public class LinkedListTest{ public stat...

军威兄的博客 326

LinkedList源码学习

文章目录LinkedList源码学习简介内部结构分析LinkedList源码分析构造方法add()方法根据位置取数据的方法根据对象得到索引的方法检查链表是否包含某对象的方法:LinkedList类常用方法测试 LinkedList源码学习 简介 LinkedList是一个实现了List接口和Deque接口的双端链表。 LinkedList底层的链表结构使它支持高效的插入和删除操作,另外它实现了De...

qq_24095055的博客 756

LinkedList集合源码

节点的基本结构: private static class Node<E> { E item; //表示该节点包含的值 Node<E> next; //表达当前节点的下一个节点 Node<E> prev; //表示当前节点的上一个节点 Node(Node<E> prev, E...

zxk082829的博客 176

Java集合之LinkedList源码解析

而第二个方法 remove(Object o) 是删除指定元素,这个方法要依次遍历节点进行元素的比较,最坏情况下要比较到最后一个元素,比调用 node 方法更慢,时间复杂度为 O(n)。如上图所示,LinkedList底层使用的双向链表结构,有一个头结点和一个尾结点,双向链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作。首先,将last引用赋值给l,接着new了一个新节点E2,并且E2的prve指向l,接着将新节点E2赋值为last。

XING的博客 901
上一篇: ArrayList源码
下一篇: hashmap1.8源码
张潇洒啊
博客等级 码龄9年 1粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值