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;
    else
        l.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) { // 如果要删除的元素为 null
        for (Node<E> x = first; x != null; x = x.next) { // 遍历链表
            if (x.item == null) { // 如果节点的元素为 null
                unlink(x); // 删除节点
                return true; // 返回 true 表示删除成功
            }
        }
    } else { // 如果要删除的元素不为 null
        for (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; // 将要删除的节点的元素设置为 null
    f.next = null; // 将要删除的节点的下一个节点设置为 null
    first = next; // 将链表的头节点设置为要删除的节点的下一个节点
    if (next == null) // 如果链表只有一个节点
        last = null; // 将链表的尾节点设置为 null
    else
        next.prev = null; // 将要删除节点的下一个节点的前驱设置为 null
    size--; // 减少链表的大小
    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的比较 

        敬请期待下一章 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

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

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

C++ 多态向上转型详解

文章目录 1 . 前言2 . 多态3 . 向上转型4 . 总结 【极客技术传送门】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 1 . 前言 此篇博文详解C的多态向上转型平台 : Qt 2 . 多态 【Q】什么是多态&#xff1f; 【A】解释如下 : 通俗来说,就是多种形态,具体…

八皇后问题(C语言/C++)超详细讲解/由浅入深---深入八皇后问题

介绍引入 在计算机科学中&#xff0c;八皇后问题是一个经典的回溯算法问题。这个问题的目标是找出一种在8x8国际象棋棋盘上放置八个皇后的方法&#xff0c;使得没有任何两个皇后能够互相攻击。换句话说&#xff0c;每一行、每一列以及对角线上只能有一个皇后。 想象一下&…

C++多态性——(3)动态联编的实现——虚函数

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 成功的秘诀就在于多努力一次&#xff…

Sam Altman的一天被曝光!每天15小时禁食、服用小剂量安眠药,尽可能避免开会

Sam Altman在经历了几天混乱的管理重组后&#xff0c;重新回到了OpenAI的CEO位置。在日常生活中&#xff0c;奥特曼与许多科技行业高管一样&#xff0c;痴迷于延长自己的寿命。 据报道&#xff0c;他还为应对末日场景&#xff08;致命合成病毒的释放、核战争和人工智能攻击等&…

【AIGC摄影构图prompt】与重不同的绘制效果,解构主义+优美连拍提示效果

提取关键词构图&#xff1a; 激进解构主义 在prompt中&#xff0c;激进解构主义的画面效果可能是一种颠覆传统和权威的视觉呈现。这种画面可能以一种极端或激烈的方式表达对现有社会结构和观念体系的批判和质疑。 具体来说&#xff0c;这种画面效果可能包括&#xff1a; 破…

流媒体学习之路(WebRTC)——Pacer与GCC(5)

流媒体学习之路(WebRTC)——Pacer与GCC&#xff08;5&#xff09; —— 我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost目标&#xff1a;可以让大家熟悉各类Qos能力、带宽估计能力&#xff0c;提供每个环节关键参数调节接口并实现一个json全…

相关性与P值

相关性与P值 0 FQA&#xff1a;1 相关性与显著性的关系2 相关性分析3 使用medcalc进行相关性分析&#xff1a;参考文章&#xff1a; 0 FQA&#xff1a; 主要描述相关性和p值分别代表什么意义&#xff1f; 以及如何使用medcalc计算相关性和p值。 Q1&#xff1a;p值代表什么意义…

Document对象详解

前言 在前端开发中&#xff0c;DOM&#xff08;文档对象模型&#xff09;扮演着重要的角色。它允许我们使用JavaScript来与网页文档进行交互&#xff0c;实现动态的网页效果。DOM的核心部分之一就是Document对象&#xff0c;它代表了整个HTML文档。在本篇博客中&#xff0c;我们…

【笔记】书生·浦语大模型实战营——第一课

群公告 1月3日*更新 第一次课程视频链接&#xff1a;https://www.bilibili.com/video/BV1Rc411b7ns/&#xff0c;第一次课程只需要记笔记&#xff0c;没有作业。第一次课程(1月3日)和第二次课程(1月5日)到本周末(1月7日)截止&#xff0c;笔记记录在 知乎/CSDN/Github 或者任何你…

2023年互联网公司年度崩盘报告

B站崩了两次 2023年3月5日晚20:20左右&#xff0c;许多网友表示在使用B站时&#xff0c;手机和电脑端都无法访问视频详情页&#xff0c;且手机端无法查看收藏夹与历史记录。 8月4日晚间&#xff0c;距离上次事故5个月后&#xff0c;又有许多网友反馈B站图片&#xff08;视频封…

定时器PWM控制RGB彩灯案例

1.脉冲宽度调制PWM PWM&#xff08;Pulse Width Modulation&#xff09;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术&#xff0c;广泛应用在测量、通信、工控等方面。   PWM的一个优点是从处理器到​​ ​被控系统​​​信号…

软碟通UltraISO制作U盘安装Ubuntu

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

5年经验之谈 —— 为什么要做自动化测试?

自动化测试是一种软件测试方法&#xff0c;通过编写和使用自动化脚本和工具&#xff0c;以自动执行测试用例并生成结果 自动化旨在替代手动测试过程&#xff0c;提高测试效率和准确性 自动化测试可以覆盖多种测试类型&#xff0c;包括功能测试、性能测试、安全测试等&#xf…

网工内推 | 网络工程师,NP认证优先,上市公司,包吃,最高15薪

01 无锡先导智能装备股份有限公司 招聘岗位&#xff1a;高级网络工程师 职责描述&#xff1a; 1.依据项目规划方案提供硬件及网络方案设计&#xff1b; 2.面向客户提供网络技术支持&#xff0c;包括故障的解决、性能的优化、日常维护等&#xff1b; 3.和合作伙伴、供应商的技术…

NLP论文阅读记录 - 2021 | RefSum:重构神经总结

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.前提堆叠重新排序 三.本文方法3.1 总结为两阶段学习3.1.1 基础系统3.1.2 元系统 3.2 重构文本摘要3.2.1 重构3.2.2 预训练重构3.2.3 微调重构3.2.4 应用场景3.2.4.1 重构为基础学习者3.2.4.2 …

Vue学习计划-Vue3--核心语法(一)OptionsAPI、CompositionAPI与setup

1. OptionsAPI与CompositionAPI Vue2的API设计是Options(配置)风格的Vue3的API设计是Composition(组合)风格的 Options API的弊端&#xff1a; Options类型的API&#xff0c;数据、方法、计算属性等&#xff0c;是分散在&#xff1a;data、methods、computed中的&#xff0c;若…

【Linux Shell】1. Shell 简述

文章目录 【 1. Shell 解释器、Shell语言、Shell脚本 】【 2. Shell 环境 】【 3. 一个简单的 Shell 脚本 】3.1 Shell 脚本的编写3.2 Shell 脚本的运行3.2.1 作为可执行程序运行 Shell 脚本3.2.2 作为解释器参数运行 Shell 脚本 【 1. Shell 解释器、Shell语言、Shell脚本 】 …

正则表达式 详解,10分钟学会

大家好&#xff0c;欢迎来到停止重构的频道。 本期我们讨论正则表达式。 正则表达式是一种用于匹配和操作文本的工具&#xff0c;常用于文本查找、文本替换、校验文本格式等场景。 正则表达式不仅是写代码时才会使用&#xff0c;在平常使用的很多文本编辑软件&#xff0c;都…

华为月薪25K的自动化测试工程师到底要会那些技能!

​前言 3年自动化测试软件测试工程师职业生涯中&#xff0c;我所经历过的项目都是以自动化测试为主的。由于自动化测试是一个广泛的领域&#xff0c;我将自己的经验整理了一下分享给大家&#xff0c;话不多说&#xff0c;直接上干货。 自动化测试的目标和实践选择合适的自动化…