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 ...
随机推荐
- Python爬虫抓取 python tutorial中文版,保存为word
看到了中文版的python tutorial,发现是网页版的,刚好最近在学习爬虫,想着不如抓取到本地 首先是网页的内容 查看网页源码后发现可以使用BeautifulSoup来获取文档的标题和内容,并保 ...
- HDU 4886 TIANKENG’s restaurant(Ⅱ) ( 暴力+hash )
TIANKENG’s restaurant(Ⅱ) Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 130107/65536 K (Ja ...
- bzoj2582 [Usaco2012Jan]Bovine Alliance
[Usaco2012Jan]Bovine Alliance Time Limit: 2 Sec Memory Limit: 128 MB Description Bessie and her bovi ...
- SQL数据库—<6>存储过程
Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...
- Flask-Login的实现
Flask-Login Flask-Login 为 Flask 提供用户 session 的管理机制.它可以处理 Login.Logout 和 session 等服务. 作用: 将用户的 id 储存在 ...
- linux上传与下载文件命令
//文件从Linux系统上传到其他系统. sz空格+文件名 //文件从其他系统下载到Linux系统. rz //之后会弹出路径选择框,选择文件,即可下载到当前路径.
- linux---postgresql的安装和配置
postgresql的安装:源码安装(推荐):http://my.oschina.net/hippora/blog/375292 1.tar -xjvf postgresql-9.3.4.tar.bz ...
- python基础--逻辑运算
#and or not#and 且 :两边都为真才是真#or 或:一个真就是真(一真为真)#ont 非:相反#优先级:1.not>and>or#同一优先级由左向右以此计算!#列子:prin ...
- Motan框架初体验
1.什么是Motan? Motan是一套基于java开发的RPC框架,除了常规的点对点调用外,motan还提供服务治理功能,包括服务节点的自动发现.摘除.高可用和负载均衡等.Motan具有良好的扩展性 ...
- 为什么不能在shell脚本中执行source /etc/profile或者source ~/.bashrc问题?
执行脚本时,其中的命令是在一个子shell中执行的.子shell继承了父shell的环境变量,但无法修改他们,或者说所做的修改仅对子shell有效.