LinkedList部分底层源码分析

JDK版本为1.8.0_271,以插入和删除元素为例,LinkedList部分源码如下:

//属性,底层结构为双向链表
transient Node<E> first; //记录第一个结点的位置
transient Node<E> last; //记录最后一个结点的尾元素
transient int size = 0; //记录链表的元素个数//内部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;}
}//构造器
public LinkedList() {
}//方法:add()相关方法
public boolean add(E e) {linkLast(e); //默认把新元素链接到链表尾部return true;
}// 尾部插入一个新节点
void linkLast(E e) {final Node<E> l = last; //用 l 记录原来的最后一个结点//创建新结点final Node<E> newNode = new Node<>(l, e, null);//现在的新结点是最后一个结点了last = newNode;//如果l==null,说明原来的链表是空的if (l == null)//那么新结点同时也是第一个结点first = newNode;else//否则把新结点链接到原来的最后一个结点的next中l.next = newNode;//元素个数增加size++;//修改次数增加modCount++;
}//方法:获取get()相关方法
public E get(int index) {// 校验index是否越界,合法范围:[0,size)checkElementIndex(index);return node(index).item;
} //方法:插入add()相关方法
public void add(int index, E element) {checkPositionIndex(index); // 校验index是否越界,合法范围:[0,size)if (index == size)//如果index==size,链接到当前链表的尾部linkLast(element);elselinkBefore(element, node(index));
}// 查找index位置节点
Node<E> node(int index) {// assert isElementIndex(index);/*index < (size >> 1)采用二分思想,先将index与长度size的一半比较,如果index<size/2,就只从位置0往后遍历到位置index处;如果index>size/2,就只从位置size往前遍历到位置index处。这样可以减少一部分不必要的遍历。*///如果index<size/2,就从前往后找目标结点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;}
}//把新结点插入到[index]位置的结点succ前面,succ是[index]位置对应的结点
void linkBefore(E e, Node<E> succ) {// assert succ != null;final Node<E> pred = succ.prev; //[index]位置的前一个结点//新结点的prev是原来[index]位置的前一个结点//新结点的next是原来[index]位置的结点final Node<E> newNode = new Node<>(pred, e, succ);//[index]位置对应的结点的prev指向新结点succ.prev = newNode;//如果原来[index]位置对应的结点是第一个结点,那么现在新结点是第一个结点if (pred == null)first = newNode;elsepred.next = newNode;//原来[index]位置的前一个结点的next指向新结点size++;modCount++;
}//方法:remove()相关方法
public boolean remove(Object o) {//分o是否为空两种情况if (o == null) {//找到o对应的结点xfor (Node<E> x = first; x != null; x = x.next) {if (x.item == null) {unlink(x);//删除x结点return true;}}} else {//找到o对应的结点xfor (Node<E> x = first; x != null; x = x.next) {if (o.equals(x.item)) {unlink(x);//删除x结点return true;}}}return false;
}
// 将节点x从链表中取下
E unlink(Node<E> x) {//x是要被删除的结点// assert x != null;final E element = x.item;//被删除结点的数据final Node<E> next = x.next;//被删除结点的下一个结点final Node<E> prev = x.prev;//被删除结点的上一个结点//如果被删除结点的前面没有结点,说明被删除结点是第一个结点if (prev == null) {//那么被删除结点的下一个结点变为第一个结点first = next;} else {//被删除结点不是第一个结点//被删除结点的上一个结点的next指向被删除结点的下一个结点prev.next = next;//断开被删除结点与上一个结点的链接x.prev = null;//使得GC回收}//如果被删除结点的后面没有结点,说明被删除结点是最后一个结点if (next == null) {//那么被删除结点的上一个结点变为最后一个结点last = prev;} else {//被删除结点不是最后一个结点//被删除结点的下一个结点的prev执行被删除结点的上一个结点next.prev = prev;//断开被删除结点与下一个结点的连接x.next = null;//使得GC回收}//把被删除结点的数据也置空,使得GC回收x.item = null;//元素个数减少size--;//修改次数增加modCount++;//返回被删除结点的数据return element;
}// 删除index位置的节点
public E remove(int index) { //index是要删除元素的索引位置// 校验index范围checkElementIndex(index);// 将节点x从链表中取下return unlink(node(index));
}// 插入新节点链表头结点
public void addFirst(E e) {linkFirst(e);
}
// 链接节点到链表头
private void linkFirst(E e) {final Node<E> f = first;	// 获取链表头节点final Node<E> newNode = new Node<>(null, e, f);	// 新建节点first = newNode;	// 更新头结点if (f == null)	// 原链表为空时last = newNode;	// 将链表last指向新的头结点else	// 双端链表,将原头结点的prev指向新的头结点f.prev = newNode;size++;	// 链表节点数+1modCount++;	// 链表修改次数+1
}// 获取链表的头结点的元素
public E getFirst() {final Node<E> f = first;if (f == null)throw new NoSuchElementException();return f.item;
}
// addLast尾插法插入节点,getLast获取链表尾结点

插入删除结点的过程如图所示:

  • 只有1个元素的LinkedList

  • 包含4个元素的LinkedList

在这里插入图片描述

  • add(E e)方法

  • add(int index,E e)方法

在这里插入图片描述

  • remove(Object obj)方法

在这里插入图片描述

  • remove(int index)方法

在这里插入图片描述

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

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

相关文章

域控软件安全隔离关键技术剖析:MCU域 VS SOC域

安全隔离的需求 功能安全开发中&#xff0c;软件阶段由软件V模型左边的软件安全需求SSR开始。SSR是从技术安全需求TSR中提取出软件的功能安全需求&#xff0c;大多数情况下具有不同的ASIL等级。 图1 功能安全软件开发V模型 随后&#xff0c;软件安全需求会被分配到软件架构中的…

AcWing-滑动窗口

单调队列模板题&#xff1a; 所需知识&#xff1a;单调队列 利用双端队列来实现单调队列&#xff1b; 双端队列与普通队列的不同处&#xff1a;双端队列删除元素时既可以删除队头又可以删掉队尾&#xff0c;其可以较好的维护单调队列的单调性&#xff1b; 双端队列的定义及…

蓝桥杯-数组切分

问题描述 已知一个长度为 N 的数组: A1,A2,A3,...AN 恰好是1~ N的一个排列。现 在要求你将 4 数组切分成若干个 (最少一个,最多 N 个)连续的子数组,并且 每个子数组中包含的整数恰好可以组成一段连续的自然数。 例如对于 4 1,3,2,4,一共有 5 种切分方法: 1324:每个单独的数显然…

卫星影像联合无人机实现农业保险全生命周期监管监测

随着科技的进步&#xff0c;农业保险监管系统的发展日新月异。特别是近年来&#xff0c;随着卫星技术与无人机技术的结合&#xff0c;为农业保险监管系统带来了前所未有的革新。本文将深入探讨如何利用卫星与无人机方案构建高效的农业保险监管系统&#xff0c;并结合实例进行说…

Dart 中 JS 互操作的历史

由于在 Dart 3.3 中达到了令人兴奋的 JavaScript 互操作里程碑&#xff0c;Wasm 的支持刚刚登陆当前的 Flutter 测试版。为了庆祝这一里程碑&#xff0c;我们回顾了 Dart 和 JavaScript 互操作性长达十年的历程。 从 Dart 诞生之初&#xff0c;互操作性就是一个核心重点。2011…

golangci-lint 报错

File is not gci-ed with --skip-generated -s standard,default (gci) golangci-lint 报错上面的错解决办法&#xff1a; 1. 文件换行需要换成"LF" 而不是"CRLF" ---->>> 我用的goland IDE&#xff0c;随便在这个文件删除一个空行&#xff…

20240412,引用,函数高级

老子什么时候能找到一个很爱我还和我一样喜欢看日出日落的对象 一&#xff0c;引用 给变量起别名&#xff0c;数据类型 & 别名原名&#xff1b;引用一定要初始化&#xff0c;初始化之后不能更改 #include <iostream> using namespace std; int main() {int a 10;i…

导入导出之使用EasyExcel快速进行表格导出

使用 EasyExcel 快速进行表格导入导出操作 在日常工作中&#xff0c;表格的导入和导出是常见的需求。针对这种情况&#xff0c;EasyExcel 提供了便捷的解决方案&#xff0c;可以快速地实现 Excel 表格的导入和导出操作。本文将介绍如何使用 EasyExcel 进行表格导出&#xff0c…

Linux权限的讲解

目录 1、用户的分级 2、用户的身份 3、文件的权限属性 3.1 文件类型 4、chmod 4.1 用八进制形式更改权限 5、chown与chgrp 6、umask 结语 前言&#xff1a; 在Linux下虽然一切都是文件&#xff0c;但是由于文件的权限不一样&#xff0c;导致访问或更改文件存在局限性…

Web App 入门指南:构建预测模型 App 的利器(shiny)

Web App 入门指南&#xff1a;构建预测模型 App 的利器 简介 近年来&#xff0c;随着机器学习和人工智能技术的快速发展&#xff0c;预测模型在各行各业得到了广泛应用。为了方便地部署和使用预测模型&#xff0c;将模型构建成 Web App 是一种非常好的选择。Web App 无需下载…

Bitmap OOM

老机器Bitmap预读仍然OOM&#xff0c;无奈增加一段&#xff0c;终于不崩溃了。 if (Build.VERSION.SDK_INT < 21)size 2; 完整代码&#xff1a; Bitmap bitmap; try {//Log.e(Thread.currentThread().getStackTrace()[2] "", surl);URL url new URL(surl);…

python|map

# 定义一个平方函数 def square(x): return x ** 2 # 创建一个数字列表 numbers [1, 2, 3, 4, 5] # 使用 map 函数将平方函数应用于列表中的每个元素 squares map(square, numbers) #将numbers绑定上一个函数 print(type(square)) print(square)# 将结果转换为列表…

【CSS】背景模糊,不模糊主体文字

问题 背景模糊&#xff0c;不模糊文本 效果图 t1 t2 t3 实现思路 自定义css变量存储图片地址&#xff0c;方便后期更改使用伪元素实现背景模糊达到不遮挡主体文本 transform: scale(1.5)吧图片放大1.5倍&#xff0c;避免设置背景模糊出现白边。 overflow: hidden 超出隐藏&…

上海人工智能实验室的书生·浦语大模型学习笔记(第二期第三课——下篇)

书生浦语是上海人工智能实验室和商汤科技联合研发的一款大模型&#xff0c;这次有机会参与试用&#xff0c;特记录每次学习情况。 一、基础作业 2、在 InternLM Studio 上部署茴香豆技术助手 本次选用 InternLM2-Chat-7B 作为本地基础模型&#xff0c;同时用智浦的GLM作为远…

论文分享 | FAST'23 阿里云提出的针对SMR优化的存储引擎SMRSTORE

今天分享的一篇最近阅读的论文是FAST23的SMRstore: A Storage Engine for Cloud Object Storage on HM-SMR Drives。 https://www.usenix.org/conference/fast23/presentation/zhou 这篇文章是由阿里巴巴公司完成的&#xff0c;在这篇文章中&#xff0c;团队针对SMR的特性提出了…

C++ AVL树底层实现原理

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;C知识分享⏪   &#x1f69a;代码仓库:C高阶&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多C知识   &#x1f51d;&#x1f51d; 目录 前言 AVL 树 1.1 AVL树的概念 1.2 AVL树…

[大模型]Qwen1.5-7B-Chat FastApi 部署调用

Qwen1.5-7B-Chat FastApi 部署调用 环境准备 在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器&#xff0c;如下图所示镜像选择 PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8&#xff08;11.3 版本以上的都可以&#xff09;。 接下来打开刚刚租用服务器的 Jupyt…

vivado 使用 ILA 默认仪表板

使用 ILA 默认仪表板 ILA 仪表板 &#xff08; 请参阅下图 &#xff09; 是给定 ILA 核相关的所有状态和控制信息的集中显示位置。刷新硬件器件并首次检测到 ILA 核时 &#xff0c; 将自动打开该核的默认 ILA 仪表板。如果需要手动打开或重新打开此仪表板 &#xff0c; 只…

性能优化 - 你知道CSS有哪些优化方案吗

难度级别:中高级及以上 提问概率:70% CSS是前端开发工作中必不可少的技能之一,同时也是网页开发中必不可少的重要元素之一。但很多人所开发的项目本身对性能要求并不高,再加上项目周期紧张,久而久之,也就容易养成不考虑细节的习惯,觉得C…

每日OJ题_01背包①_牛客DP41 【模板】01背包(滚动数组优化)

目录 牛客DP41 【模板】01背包 问题一解析 问题二解析 解析代码 滚动数组优化代码 牛客DP41 【模板】01背包 【模板】01背包_牛客题霸_牛客网 #include <iostream> using namespace std;int main() {int a, b;while (cin >> a >> b) { // 注意 while 处…