LinkedList底层代码解析笔记

LinkedList是属于Sequence List,故遍历是用迭代器更快;
LinkedList继承自AbstractSequenceList、实现了List及Deque接口。其实AbstractSequenceList已经实现了List接口,这里标注出List只是更加清晰而已。AbstractSequenceList提供了List接口骨干性的实现以减少实现List接口的复杂度。Deque接口定义了双端队列的操作。
附上一张构造图(蓝色线条是继承,绿色线条是接口实现)如下:

其数据结构如下:

更清晰些:

说明:如上图所示,LinkedList底层使用的双向链表结构,有一个头结点和一个尾结点,双向链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作。
类的内部类:

说明:内部类Node就是实际的结点,用于存放实际元素的地方。
类的属性:

说明:LinkedList的属性非常简单,一个头结点、一个尾结点、一个表示链表中实际元素个数的变量。注意,头结点、尾结点都有transient关键字修饰,这也意味着在序列化时该域是不会序列化的。
LinkedList(Collection<? extends E>)型构造函数:

this();调用无参构造方法; addAll(c);添加集合中的所有的元素:
说明:会调用无参构造函数,并且会把集合中所有的元素添加到LinkedList中。
核心函数分析:

说明:add函数用于向LinkedList中添加一个元素,并且添加到链表尾部。具体添加到尾部的逻辑是由linkLast函数完成的;
如下:

说明:对于添加一个元素至链表中会调用add方法 -> linkLast方法。


说明:参数中的index表示在索引下标为index的结点(实际上是第index + 1个结点)的前面插入。在addAll函数中,addAll函数中还会调用到node函数,get函数也会调用到node函数,此函数是根据索引下标找到该结点并返回,具体代码如下

说明:在根据索引查找结点时,会有一个小优化,结点在前半段则从头开始遍历,在后半段则从尾开始遍历,这样就保证了只需要遍历最多一半结点就可以找到指定索引的结点。

如上在调用remove移除结点时,会调用到unlink函数,unlink函数具体如下:

说明:将指定的结点从链表中断开,不再累赘。设为null后,GC机制会处理掉;
清空所有的方法:

需要将每个元素的item,next,prev都设为空;


前面linkLast()方法已经分析过了,其实同理;当理解双向链表结构,其实就很简单了;
总结:
有些说法认为LinkedList做插入和删除更快,这种说法其实是不准确的:
(1)LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Entry的引用地址
(2)ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址
所以,如果待插入、删除的元素是在数据结构的前半段尤其是非常靠前的位置的时候,LinkedList的效率将大大快过ArrayList,因为ArrayList将批量copy大量的元素;越往后,对于LinkedList来说,因为它是双向链表,所以在第2个元素后面插入一个数据和在倒数第2个元素后面插入一个元素在效率上基本没有差别,但是ArrayList由于要批量copy的元素越来越少,操作速度必然追上乃至超过LinkedList。
从这个分析看出,如果你十分确定你插入、删除的元素是在前半段,那么就使用LinkedList;如果你十分确定你删除、删除的元素在比较靠后的位置,那么可以考虑使用ArrayList。如果你不能确定你要做的插入、删除是在哪儿呢?那还是建议你使用LinkedList吧,因为一来LinkedList整体插入、删除的执行效率比较稳定,没有ArrayList这种越往后越快的情况;二来插入元素的时候,弄得不好ArrayList就要进行一次扩容,记住,ArrayList底层数组扩容是一个既消耗时间又消耗空间的操作。
LinkedList底层代码解析笔记的更多相关文章
- ArrayList底层代码解析笔记
通过底层代码可以学习到很多东西: public class ArrayList<E> extends AbstractList<E> implements List<E& ...
- 笔记-爬虫-js代码解析
笔记-爬虫-js代码解析 1. js代码解析 1.1. 前言 在爬取网站时经常会有js生成关键信息,而且js代码是混淆过的. 以瓜子二手车为例,直接请求https://www.guaz ...
- java笔记 -- java简单结构代码解析及注释
结构代码解析 public class FirstSample { public static void main(String[] args) { System.out.println(2.0-1. ...
- ArrayList和LinkedList的底层代码实现思想
ArrayList是Java众多集合类中的一个,实现List接口,List的父接口是Collection.ArrayList底层的数据结构是线性表中的顺序表,底层是一个长度可以动态增长的数组.数组有很 ...
- 【论文笔记】AutoML for MCA on Mobile Devices——论文解读与代码解析
理论部分 方法介绍 本节将详细介绍AMC的算法流程.AMC旨在自动地找出每层的冗余参数. AMC训练一个强化学习的策略,对每个卷积层会给出其action(即压缩率),然后根据压缩率进行裁枝.裁枝后,A ...
- Java集合---LinkedList源码解析
一.源码解析1. LinkedList类定义2.LinkedList数据结构原理3.私有属性4.构造方法5.元素添加add()及原理6.删除数据remove()7.数据获取get()8.数据复制clo ...
- LinkedList源码解析
LinkedList是基于链表结构的一种List,在分析LinkedList源码前有必要对链表结构进行说明.1.链表的概念链表是由一系列非连续的节点组成的存储结构,简单分下类的话,链表又分为单向链表和 ...
- [Java] LinkedList / Queue - 源代码学习笔记
简单地画了下 LinkedList 的继承关系,如下图.只是画了关注的部分,并不是完整的关系图.本博文涉及的是 Queue, Deque, LinkedList 的源代码阅读笔记.关于 List 接口 ...
- ava集合---LinkedList源码解析
一.源码解析 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E ...
随机推荐
- Scrapy框架: 通用爬虫之XMLFeedSpider
步骤01: 创建项目 scrapy startproject xmlfeedspider 步骤02: 使用XMLFeedSpider模版创建爬虫 scrapy genspider -t xmlfeed ...
- [FW]使用kprobes查看内核内部信息
使用printk打印变量等方法,是调试内核的有效方法之一,但是这种方法必须重新构建并用新内核启动,调试效率比较低.以内核模块的方式使用kprobes.jprobes,就可以在任意地址插入侦测器,执行包 ...
- Codeforces 492D Vanya and Computer Game
D. Vanya and Computer Game time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- link address
http://en.wikipedia.org/wiki/Software_design http://www.codeproject.com/Articles/70061/Architecture- ...
- elasticsearch 英文数字组合字符串模糊检索
不分词,然后用wildcard查询 { "query": { "wildcard": { "字段名": "*123*" ...
- eclipse 附加进程调试java程序(转)
转自:http://blog.csdn.net/zhoushenghuang/article/details/54485645 第一步,启动Java程序时需要设置JVM参数 右击java项目-> ...
- Node的优点和缺点
(优点)因为Node是基于事件驱动和无阻塞的,所以非常适合处理并发请求, 因此构建在Node上的代理服务器相比其他技术实现(如Ruby)的服务器表现要好得多. 此外,与Node代理服务器交互的客户端代 ...
- Electron-vue实战(三)— 如何在Vuex中管理Mock数据
Electron-vue实战(三)— 如何在Vuex中管理Mock数据 作者:狐狸家的鱼 本文链接:Vuex管理Mock数据 GitHub:sueRimn 在vuex中管理mock数据 关于vuex的 ...
- Java多线程状态切换
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11426573.html 线程状态 NEW RUNNABLE BLOCKED WAITING TIMED ...
- shell中的空格【转载】
1.定义变量时, =号的两边不可以留空格. eg: gender=femal————right gender =femal———–wrong gender= femal———–wrong gender ...