Java LinkedList解密

一、LinkedList最底层的原理

        LinkedList其实底层是链表:

        当初始化的时候,会将链表这个节点的值、prev指针和next指针初始化。

二、LinkedList初始化

 

        无参构造并没有做什么。有参构造会先调用无参构造,然后调用addAll方法将链表的节点都初始化:

二、增加元素

2.1 add(object)

        调用了linkLast方法。就是在尾部添加元素

2.1.1 linkLast

 

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; // 否则将新节点链接到链表的尾部size++; // 增加链表的元素个数
}

         常见的双向链表插入元素的逻辑。不得不说,jdk的代码还是很简洁的。这里画个图示:

        当插入空链表时:

        当链表中有一个元素时:

 

二、删除元素 

2.1 remove() 

 

        无参的remove调用的是removeFirst(),可以看出是从头开始删的。这个函数放在后面讲。

2.2 remove(object)

 

        删除指定的元素,这个删除逻辑和ArrayList一样,有兴趣的可以看看我讲解的ArrayList源码:Java ArrayList解密-CSDN博客

public boolean remove(Object o) {if (o == null) { // 如果要删除的元素为 nullfor (Node<E> x = first; x != null; x = x.next) { // 遍历链表if (x.item == null) { // 如果节点的元素为 nullunlink(x); // 删除节点return true; // 返回 true 表示删除成功}}} else { // 如果要删除的元素不为 nullfor (Node<E> x = first; x != null; x = x.next) { // 遍历链表if (o.equals(x.item)) { // 如果节点的元素等于要删除的元素unlink(x); // 删除节点return true; // 返回 true 表示删除成功}}}return false; // 如果链表中不包含要删除的元素,则返回 false 表示删除失败
}

 2.2.1 unlink()

        顾名思义,其实就是取消这个节点和链表的连接关系。他更新要删除的这个节点的prev和next指针,并将当前节点置为null便于GC

 

E unlink(Node<E> x) {final E element = x.item; // 获取要删除节点的元素final Node<E> next = x.next; // 获取要删除节点的下一个节点final Node<E> prev = x.prev; // 获取要删除节点的上一个节点if (prev == null) { // 如果要删除节点是第一个节点first = next; // 将链表的头节点设置为要删除节点的下一个节点} else {prev.next = next; // 将要删除节点的上一个节点指向要删除节点的下一个节点x.prev = null; // 将要删除节点的上一个节点设置为空}if (next == null) { // 如果要删除节点是最后一个节点last = prev; // 将链表的尾节点设置为要删除节点的上一个节点} else {next.prev = prev; // 将要删除节点的下一个节点指向要删除节点的上一个节点x.next = null; // 将要删除节点的下一个节点设置为空}x.item = null; // 将要删除节点的元素设置为空size--; // 减少链表的元素个数return element; // 返回被删除节点的元素
}

2.3 removeFirst() 

 

        先判断链表内有没有元素,然后调用unlinkFist()方法删除

2.3.1 unlinkFist()

 

private E unlinkFirst(Node<E> f) {final E element = f.item; // 获取要删除的节点的元素final Node<E> next = f.next; // 获取要删除的节点的下一个节点f.item = null; // 将要删除的节点的元素设置为 nullf.next = null; // 将要删除的节点的下一个节点设置为 nullfirst = next; // 将链表的头节点设置为要删除的节点的下一个节点if (next == null) // 如果链表只有一个节点last = null; // 将链表的尾节点设置为 nullelsenext.prev = null; // 将要删除节点的下一个节点的前驱设置为 nullsize--; // 减少链表的大小return element; // 返回被删除节点的元素
}

        说白了就是把first指针指向的节点去掉,然后将first指针指向下一个节点,再将当前first的prev置为null

2.4 removeLast() 

        逻辑上和removeFirst()差不多,就不多赘述了。

 

三、修改

3.1 set(index, object)

public E set(int index, E element) {checkElementIndex(index); // 检查索引是否超出范围Node<E> x = node(index); // 获取要替换的节点E oldVal = x.item; // 获取要替换节点的元素x.item = element; // 将要替换的节点的元素设置为指定元素return oldVal; // 返回替换前的元素
}

3.1.1 node方法

        找到索引位置的元素。

        比较有意思的点是,他会判断索引位置在链表前半段还是后半段。如果在前半段,就从前面遍历链表;如果在后半段,就从后面遍历链表 

 

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.1 get(index) 

        查找索引处元素 

 

        检查索引后,调用node方法找到元素,node方法在前面讲过了,这里略去。

4.2 indexOf(object) 

        查找指定元素

 

         逻辑和ArrayList的indexOf一致,都是直接遍历

五、和ArrayList的比较 

        敬请期待下一章 

 

 

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

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

相关文章

什么是自动化测试?为啥要学自动化测试?

什么是自动化测试&#xff0c;接着对常用的自动化测试框架进行了对比分析&#xff0c;最后&#xff0c;介绍了如果将自动化测试框架Cypress运用在项目中。 一、自动化测试概述 为了保障软件质量&#xff0c;并减少重复性的测试工作&#xff0c;自动化测试已经被广泛运用。在开…

基于果蝇算法优化的Elman神经网络数据预测 - 附代码

基于果蝇算法优化的Elman神经网络数据预测 - 附代码 文章目录 基于果蝇算法优化的Elman神经网络数据预测 - 附代码1.Elman 神经网络结构2.Elman 神经用络学习过程3.电力负荷预测概述3.1 模型建立 4.基于果蝇优化的Elman网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针…

软碟通UltraISO制作U盘安装Ubuntu

清华大学开源软件镜像站https://mirrors.tuna.tsinghua.edu.cn/ 从里面下载ubuntu-22.04-desktop-amd64.iso UltraISO是一款非常不错的U盘启动盘制作工具&#xff0c;一直被许多网友们所喜欢&#xff0c;使用简单、方便。 UltraISO官方下载地址&#xff1a;https://cn.ultrais…

如何删除K8S中的Pod

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

杨中科 .NET Core 第一部分.NET Standard

1)不讲C#基础语法和NET基础类库(不需要学过ASPNET等)。需要懂HTML、JavaScript、数据库等。后续会录制基础视频 2)使用Visual Studio 2019 .NET .NET Framework Windows 程序 .NET Core 跨平台程序 .NET Standard 上述两者 遵从的标准 .NET5 开始上述统称为 .NET 新建.NET Sta…

Unity中裁剪空间推导(使用FOV来调节)

文章目录 前言一、使用FOV代替之前使用的Size&#xff08;h&#xff09;1、我们可以把矩阵中使用到 h(高) 和 w(宽) 的部分使用比值替换掉。2、替换后 前言 在之前的文章中&#xff0c;我们控制透视相机使用的是SIze。但是&#xff0c;在透视相机中&#xff0c;我们使用的是FO…

线程的深入学习(一)

前言 前面文章讲述了线程的部分基本知识&#xff0c;这篇是对线程的深入学习&#xff0c;包含线程池&#xff0c;实现框架等。 1.学习如何使用Executor框架创建线程池。 2.并发工具类如CountDownLatch、CyclicBarrier等。 3.线程安全和并发集合&#xff1a; 4.学习如何使用Jav…

Cytoscape 3.10安装包下载及安装教程

Cytoscape3.10下载链接&#xff1a;https://docs.qq.com/doc/DUkpuR0RVU0JVWkFP 1、选中下载好的安装包&#xff0c;右键选择解压到“Cytoscape 3.10”文件夹 2、双击打开“Cytoscape_3_10_0_windows_64bit.exe” 3.点击“Download”&#xff0c;请耐心等待“Java”完成 4、点击…

类的加载机制、主动引用、被动引用、什么是类加载器、类加载器的分类、自定义类的加载器

类的加载机制、类加载器 类的加载时机主动引用被动引用 类加载器什么是类加载器类的加载器分类什么情况下需要自定义类的加载器 类的加载时机 主动引用 虚拟机规范中并没有强制约束何时进行加载&#xff0c;但是规范严格规定了只有下列六种情况必须对类进行加载: 当遇到new.…

适应变化:动态预测在机器学习中的作用

一、介绍 机器学习 (ML) 中的动态预测是指随着新数据的出现而不断更新预测的方法。这种方法在从医疗保健到金融等各个领域越来越重要,其中实时数据分析和最新预测可以带来更好的决策和结果。在本文中,我将讨论机器学习中动态预测的概念、其优势、挑战以及在不同领域的…

约束满足问题改进技术:基于变量和赋值次序的启发式

回溯搜索的通用算法的问题与改进思路 • 需改善无信息回溯搜索算法的性能。 • 通用改进方法的思路&#xff1a; – 下一步该给哪个变量赋值&#xff0c; 按什么顺序给该变量赋值&#xff1f; – 每步搜索应该做怎样的推理&#xff1f; 当前变量的赋值会对其他未赋值变量产…

【Java EE初阶五】wait及notify关键字

1. wait和notify的概念 所谓的wait和notify其实就是等待、通知机制&#xff1b;该机制的作用域join类似&#xff1b;由于多个线程之间是随机调度的&#xff0c;引入wait和notify就是为了能够从应用层面上&#xff0c;干预到多个不同线程代码的执行顺序&#xff0c;此处的干预&a…