LinkedList源码分析

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

成员变量

private transient Entry<E> header = new Entry<E>(null, null, null);
链表头元素

private transient int size = 0;
链表大小

构造方法

public LinkedList() {
		header.next = header.previous = header;
	}
无参构造。初始化链表头,将其next、previoous都指向其自身。

public LinkedList(Collection<? extends E> c) {
		this();
		addAll(c);
	}
该构造首先调用无参构造,然后将Collection中的元素加入到集合中。

方法

getFirst

public E getFirst() {
		if (size == 0)
			throw new NoSuchElementException();

		return header.next.element;
	}
返回链表中的第一个元素

getLast

public E getLast() {
		if (size == 0)
			throw new NoSuchElementException();

		return header.previous.element;
	}
返回链表中最后一个元素,由于其内部实现是双向链表,故直接调用header.previous.element即可。

removeFirst

public E removeFirst() {
		return remove(header.next);
	}
删除链表中的第一个元素,并返回其值,具体实现参见remove方法

removeLast

public E removeLast() {
		return remove(header.previous);
	}
删除链表中最后一个元素,并返回其值

addFirst

public void addFirst(E e) {
		addBefore(e, header.next);
	}
在链表头部插入一个元素

addLast

public void addLast(E e) {
		addBefore(e, header);
	}
在链表添加尾部插入一个元素

contains

public boolean contains(Object o) {
		return indexOf(o) != -1;
	}
检查是否包含指定元素

size

public int size() {
		return size;
	}
返回链表中元素的个数

add

public boolean add(E e) {
		addBefore(e, header);
		return true;
	}
在链表尾部加入一个元素
public void add(int index, E element) {
		addBefore(element, (index == size ? header : entry(index)));
	}
在某个位置加入元素

remove

public boolean remove(Object o) {
		if (o == null) {
			for (Entry<E> e = header.next; e != header; e = e.next) {
				if (e.element == null) {
					remove(e);
					return true;
				}
			}
		} else {
			for (Entry<E> e = header.next; e != header; e = e.next) {
				if (o.equals(e.element)) {
					remove(e);
					return true;
				}
			}
		}
		return false;
	}
删除某个元素,首先判断元素是否为null,然后进行相关的查找。

public E remove(int index) {
		return remove(entry(index));
	}
删除某一位置的元素

addAll

public boolean addAll(Collection<? extends E> c) {
		return addAll(size, c);
	}
将集合添加到链表的尾部
public boolean addAll(int index, Collection<? extends E> c) {
		if (index < 0 || index > size) //边界范围校验
			throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
					+ size);
		Object[] a = c.toArray(); //将集合转化成数组
		int numNew = a.length; //数组的长度
		if (numNew == 0)
			return false; //空集合则不用添加
		modCount++;  //结构变动变量自增

		Entry<E> successor = (index == size ? header : entry(index)); //确定集合元素添加到哪个元素之前,记为E
		Entry<E> predecessor = successor.previous; //保存E的前一个元素
		for (int i = 0; i < numNew; i++) { //循环要加入到链表的集合,
			Entry<E> e = new Entry<E>((E) a[i], successor, predecessor); //构建元素并将其next和previous分别指向E、E.previous。
			predecessor.next = e; //将E.previous的next指向新节点,这样新节点就会插入到链表中。仔细考虑此处并没有立即将successor的previous指向新节点,而是在整个循环结束之后才处理。
			predecessor = e; //将新构建的元素赋值给predecessor,即E.previous为新插入的节点,如此反复最终将这些集合元素添加到链表中
		}
		successor.previous = predecessor; //修复E的previous指向

		size += numNew; //链表大小调整
		return true;
	}
将集合中的元素添加到链表指定位置,方法具体解释见代码后的注释。

clear

public void clear() {
		Entry<E> e = header.next;
		while (e != header) {
			Entry<E> next = e.next;
			e.next = e.previous = null;
			e.element = null;
			e = next;
		}
		header.next = header.previous = header;
		size = 0;
		modCount++;
	}
清空链表

get

public E get(int index) {
		return entry(index).element;
	}
返回某个位置的值

set

public E set(int index, E element) {
		Entry<E> e = entry(index);
		E oldVal = e.element;
		e.element = element;
		return oldVal;
	}
设置某个位置的值

indexOf

public int indexOf(Object o) {
		int index = 0;
		if (o == null) {
			for (Entry e = header.next; e != header; e = e.next) {
				if (e.element == null)
					return index;
				index++;
			}
		} else {
			for (Entry e = header.next; e != header; e = e.next) {
				if (o.equals(e.element))
					return index;
				index++;
			}
		}
		return -1;
	}
返回某个元素在链表中首次出现的位置,未找到则返回-1

lastIndexOf

public int lastIndexOf(Object o) {
		int index = size;
		if (o == null) {
			for (Entry e = header.previous; e != header; e = e.previous) {
				index--;
				if (e.element == null)
					return index;
			}
		} else {
			for (Entry e = header.previous; e != header; e = e.previous) {
				index--;
				if (o.equals(e.element))
					return index;
			}
		}
		return -1;
	}
返回某个元素在链表中最后出现的位置,未找到则返回-1

peek

public E peek() {
		if (size == 0)
			return null;
		return getFirst();
	}
返回链表中的第一元素

element

public E element() {
		return getFirst();
	}
返回链表中的第一个元素,该方法同上面的peek方法的区别在于当链表为空时,peek返回为null,而element方法抛出NoSuchElementException异常

poll

public E poll() {
		if (size == 0)
			return null;
		return removeFirst();
	}
返回链表中的第一个元素,并将其在链表中移除,当链表为空时返回null

remove

public E remove() {
		return removeFirst();
	}
返回链表中的第一个元素,并将其从链表中移除,当链表为空时抛出NoSuchElementException异常

offer

public boolean offer(E e) {
		return add(e);
	}
在链表的尾部加入元素

offerFirst

public boolean offerFirst(E e) {
		addFirst(e);
		return true;
	}
在链表的头部加入元素

offerLast

public boolean offerLast(E e) {
		addLast(e);
		return true;
	}
在链表的尾部加入元素

peekFirst

public E peekFirst() {
		if (size == 0)
			return null;
		return getFirst();
	}
返回链表第一个元素,当链表为空时返回null

peekLast

public E peekLast() {
		if (size == 0)
			return null;
		return getLast();
	}
返回链表的最后一个元素,当链表为空时返回null

entry

private Entry<E> entry(int index) {
		if (index < 0 || index >= size)
			throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
					+ size);
		Entry<E> e = header;
		if (index < (size >> 1)) {
			for (int i = 0; i <= index; i++)
				e = e.next;
		} else {
			for (int i = size; i > index; i--)
				e = e.previous;
		}
		return e;
	}
该方法为私有方法,返回某个位置的元素




keil5编程前的工程文件配置,芯片型号支持包配置,用户文件配置,启动文件配置和库函数配置-江科大stm32学习 第一天 1.start文件夹中头文件需要配置路径path,另外user和library也需要,都是同样的操作。如图,在option界面c/c++中,在倒数第二空行的三个点处添加。2.需要设置一个宏,作用是使主函数头文件包含标准库函数,操作如图:复制头文件中8296行的字符串,在option界面的c/c++中第一行define粘贴这个字符串即可。一、首先,下载芯片支持包,选择你自己的器件型号,不懂的可以看我这篇选器件的方法(默认已经注册好用户)点击编译按钮,编译成功后即可在user文件夹里添加main.c正常使用。 阅读详情

相关推荐

Python与西门子PLC数据交互实战:基于Snap7的跨平台工业通信指南

本文详细介绍了如何使用Python和Snap7库实现与西门子PLC的数据交互。内容涵盖跨平台环境搭建、连接参数配置、数据读写实战及性能优化技巧,为工业自动化、数据采集和智能制造场景提供了一套轻量、灵活且高效的通信解决方案。

vim8coder的博客 291

LinkedList 的源码分析

来源:https://www.cnblogs.com/beppezhang/p/6565325.html LinkedList是基于双向链表数据结构来存储数据的,以下是对LinkedList 的 属性,构造器 ,add(E e),remove(index),get(Index),set(inde,e)进行源码分析: 属性: 1 2 3 4 5 ...

rentian1的博客 145

用人话讲明白线性回归LinearRegression

目录 什么是回归 一元线性回归 损失函数 最小二乘估计 小结 1. 什么是回归 当我们学习一门新课程、接触一个新专业时,总会对该领域的专有名词感到困惑,甚至看完解释仍难以理解其含义。在我们一起学习machine learning的过程中,我会尽量对相关名词用“人话”做一遍解释,以减少学习的“痛苦感”。 譬如今天要学的线性“回归”,这个回归(regression)和我们平时说的“回归祖国”的回...

化简可得 1万+

集合框架08:LinkedList源码分析、ArrayList和LinkedList区别

13.16 ArrayList和LinkedList区别_哔哩哔哩_bilibili。13.15 LinkedList源码分析_哔哩哔哩_bilibili。LinkedList:无需开辟连续的空间,查询慢,增删块;ArrayList:必须开辟连续的空间,查询快,增删慢;2.ArrayList和LinkedList区别。1.LinkedList源码分析。

zhangjinajian759的博客 358

手把手教你用STM32H743+FreeRTOS+LWIP搭建物联网网关(附完整工程)

本文详细介绍了如何使用STM32H743微控制器结合FreeRTOS实时操作系统和LWIP协议栈构建高性能物联网网关。内容涵盖硬件配置、FreeRTOS任务设计、LWIP协议栈优化及物联网协议集成,提供完整工程示例,助力开发者快速实现稳定可靠的网络通信枢纽。

weixin_42623010的博客 503

vscode中创建vue快捷键

1.安装Vetur插件(扩展里面直接搜) 2.vscode 界面里面左上角选则 文件=> 首选项=> 用户代码片段=>新建全局代码片段=>在输入框中新建名称为vue.json 3.删除里面的注释,当然你也可以留着,把下面的代码粘贴进去! { // Place your 全局 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and // descri

Leon_940002463的博客 3207

不得不看的LinkedList源码分析

之前分析了一下ArrayList的源码,这篇文章继续分析LinkedList,LinkedList同样是我们平时工作中最常用的集合之一。 LinkedList都有哪些特点 LinkedList的底层是通过双向链表实现的 LinkedList逻辑上是连续的(因为LinkedList开辟的内存不是连续的),是通过存放上一个节点的引用和下一个节点的引用来实现有序的链表 相对于ArrayList来说,LinkedList查询元素的速度较慢,新增和删除元素的速度较快;但是在指定位置新增元素效率较慢,时间复杂度为O(

程铭程铭你快成名的博客 7163

【win10+RAGFlow+Ollama】搭建本地大模型助手(教程+源码)

在当今科技飞速发展的时代,人工智能(AI)已经成为各行各业不可或缺的一部分。特别是在文档处理和数据分析领域,AI的应用更是无处不在。今天,我要向大家介绍一个开源的AI框架引擎——RAGflow。它能够在深度文档理解方面执行检索增强生成(Retrieval-Augmented Generation,简称RAG),并且被认为是目前最优秀的RAG框架之一。本文将详细探讨RAGflow的创新功能、技术特点以及如何在实际应用中发挥其最大潜力。

Yooao的博客 9620

Vector,ArrayList,Linkedlist源码分析

list接口和set集合

Cocobuhui的博客 974

三相五柱式消弧线圈自动测控装置设计与实现

本文设计了一种基于STM32的三相五柱式消弧线圈自动测控装置。该装置采用信号注入法检测系统对地电容电流,通过PID自适应算法调节消弧线圈电感值,实现单相接地故障时的快速补偿。硬件系统包含信号采集、注入、控制执行等模块,软件采用Goertzel算法提取特征频率信号,结合增量式PID实现精确控制。实验结果表明,装置电容检测误差小于2%,调谐响应时间小于50ms,满足配电网对消弧线圈自动调谐的技术要求。

AI的内部世界的博客 239

SAP 创建PO时提示“不能确定任何组件”

SAP 创建委外加工的PO时提示“不能确定任何组件” 而如果BOM已经创建了,但还是提示该错误保存。 解决办法:1. BOM selection 未配置好; 2. 由于Purchasing prosessing time的设置,如果PO中的delivery time - Purchasing prosessing time是过去的日期,那么会找不到BOM,BOM的有效期需早 于PO审批的有效期。 3. BOM未...

willieyuan的博客 6122

Java Collection集合类- LinkedList 源码分析

LinkedList简介: LinkedList 是实现了 List接口 和 Deque接口 的双向链表 . LinkedList 底层的链表结构使他支持高效的插入(尾插)和删除操作,此外它实现了Deque接口,使得LinkedList也具有队列的特性;LinkedList不是线程安全的. 如果想使LinkedList 变成线程安全的,可以调用静态类 Collections类中的synchron...

WALL.E 392

PyTorch生成式人工智能(3)——使用PyTorch构建神经网络

在本节中,我们使用 PyTorch 在简单数据集上构建了一个神经网络,训练神经网络来映射输入和输出,并通过执行反向传播来更新权重值以最小化损失值,并利用 Sequential 类简化网络构建过程;介绍了获取网络中间值的常用方法,以及如何使用 save、load 方法保存和加载模型,以避免再次训练模型。

盼小辉丶的博客 1万+

ArrayList和LinkedList源码分析

ArrayList和LinkedList源码分析: package easyExcel; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.LinkedList; public class App { public static void main( String...

heqingzhou的博客 239

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

LinkedList常用源码分析

转载 https://juejin.im/post/5ca23213e51d45439732f84f 一:LinkedList简介 LinkedList是一种链表类型的数据结构,支持高效的插入和删除操作。其实现了Deque接口,使得LinkedList具有队列的特性。LinkedList类的底层实现的数据结构是一个双端的链表。 二:数据结构图分析 如图可以看出LinkedList数据结构使用双向...

从入门到入狱 3039

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

java linkedlist源码分析_Java LinkedList源码分析

简介LinkedList是一个常用的集合类,用于顺序存储元素。LinkedList经常和ArrayList一起被提及。大部分人应该都知道ArrayList内部采用数组保存元素,适合用于随机访问比较多的场景,而随机插入、删除等操作因为要移动元素而比较慢。LinkedList内部采用链表的形式存储元素,随机访问比较慢,但是插入、删除元素比较快,一般认为时间复杂都是O(1)(需要查找元素时就不是了,下面...

weixin_39789370的博客 118

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

ArrayList和LinkedList的区别和源码分析

从源码可以看出,ArrayList想要get(int index)元素时,直接返回index位置上的元素,而LinkedList需要通过for循环进行查找,虽然LinkedList已经在查找方法上做了优化,比如index < size / 2,则从左边开始查找,反之从右边开始查找,但是还是比ArrayList要慢。ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;//向左挪一位,index位置原来的数据已经被覆盖了。

weixin_62198635的博客 732
上一篇: 乔布斯《遗失的访谈》整理
下一篇: 高并发下数据库丢失更新问题
kevin0xFFFFFFFF
博客等级 码龄17年 3粉丝 79原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值