JDK源码阅读——LinkedList实现
1 继承结构图

LinkedList是List的另一种实现。继承自AbstractSequentialList
2 数据结构
LinkedList与ArrayList不同的是LinkedList底层使用双向链表进行存储,其主要数据结构如下
// 记录List长度
transient int size = 0; // 指向LinkedList第一个节点
transient Node<E> first; // 指向LinkedList最后一个节点
transient Node<E> last; // Node Class如下
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;
}
}
LinkedList的一个节点是一个Node对象,可以看到node.item记录值,并且分别有指向前一个节点和后一个节点的指针prev和next
3 构造方法
public LinkedList() {}
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
LinkedList也支持两种构造方式,无参构造和传入一个集合构造LinkedList,addAll的具体实现如下
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
for (Object o : a) {
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
初始化是size=0,可见就是利用Collection的toArray方法把c转为对象数组,然后遍历新建Node,并逐个连起来,基本的链表操作。
4 一些方法介绍
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
linkBefore方法是在succ节点之前插入一个新的节点,其执行过程大致如下图

其他方法类似也都可以通过画图的形式了解大致执行步骤,涉及链表操作,画图能更好的理解执行过程,在此不再赘述。
5 与ArrayList的异同
ArrayList和LinkedList是List的两种实现,不同的ArrayList是基于动态数组的数据结构,而LinkedList是基于双向链表的数据结构。
他们的优缺点也正是由于他们所依赖的数据结构决定的
- 对于随机存取,因为ArrayList是基于数组实现的,所以随机存取的时间复杂度为O(1),直接根据数据下标即可get或set,而LinkedList由于是使用双向链表实现,随机存取需要移动指针,时间复杂度为O(n);
- 但是对于元素的删除和增加,如果不是在List尾部操作,ArrayList中元素的删除会涉及数组元素的移动,所以复杂度O(n)会比只单纯操作几个指针的复杂度O(1)要高。
所以在日常使用中,需要根据应用场景灵活选择,对于不需要随机存取而是只进行平凡的增加和删除的场景,使用LinkedList是较好的选择。
本文来自我的个人博客:http://blog.duchangchun.com/2018/12/29/jdk_linkedlist/
JDK源码阅读——LinkedList实现的更多相关文章
- JDK源码阅读--LinkedList
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, D ...
- JDK源码阅读(三):ArraryList源码解析
今天来看一下ArrayList的源码 目录 介绍 继承结构 属性 构造方法 add方法 remove方法 修改方法 获取元素 size()方法 isEmpty方法 clear方法 循环数组 1.介绍 ...
- JDK源码阅读(一):Object源码分析
最近经过某大佬的建议准备阅读一下JDK的源码来提升一下自己 所以开始写JDK源码分析的文章 阅读JDK版本为1.8 目录 Object结构图 构造器 equals 方法 getClass 方法 has ...
- 利用IDEA搭建JDK源码阅读环境
利用IDEA搭建JDK源码阅读环境 首先新建一个java基础项目 基础目录 source 源码 test 测试源码和入口 准备JDK源码 下图框起来的路径就是jdk的储存位置 打开jdk目录,找到sr ...
- JDK源码阅读-FileOutputStream
本文转载自JDK源码阅读-FileOutputStream 导语 FileOutputStream用户打开文件并获取输出流. 打开文件 public FileOutputStream(File fil ...
- JDK源码阅读-FileInputStream
本文转载自JDK源码阅读-FileInputStream 导语 FileIntputStream用于打开一个文件并获取输入流. 打开文件 我们来看看FileIntputStream打开文件时,做了什么 ...
- JDK源码阅读-ByteBuffer
本文转载自JDK源码阅读-ByteBuffer 导语 Buffer是Java NIO中对于缓冲区的封装.在Java BIO中,所有的读写API,都是直接使用byte数组作为缓冲区的,简单直接.但是在J ...
- JDK源码阅读-RandomAccessFile
本文转载自JDK源码阅读-RandomAccessFile 导语 FileInputStream只能用于读取文件,FileOutputStream只能用于写入文件,而对于同时读取文件,并且需要随意移动 ...
- JDK源码阅读-FileDescriptor
本文转载自JDK源码阅读-FileDescriptor 导语 操作系统使用文件描述符来指代一个打开的文件,对文件的读写操作,都需要文件描述符作为参数.Java虽然在设计上使用了抽象程度更高的流来作为文 ...
随机推荐
- Windows Phone 8.1 Tiles, Notifications and Action Center
(1)Tiles Tiles 也就是磁贴,是 Windows Phone 的一大特色. 一个 Tile 其实可以看成是一个 XML,比如: <tile> <visual> &l ...
- 程序猿的还有一出路:大数据project师
非常多年前我非常郁闷地写了一篇博客<程序猿的出路在哪里?>,之所以郁闷.我记得是看了中国男足的比赛,不由自主对照自已苦逼的程序猿生涯,以前对中国软件的感情有如对中国男足,绝望到没有不论什么 ...
- 2016.3.14__CSS 定位__第六天
假设您认为这篇文章还不错.能够去H5专题介绍中查看很多其它相关文章. CSS 定位机制 CSS中一共同拥有三种基本定位机制:普通流.浮动.绝对定位. 假设不进行专门指定.全部的标签都在普通流中定位. ...
- Android 调整透明度的图片查看器
本文以实例讲解了基于Android的可以调整透明度的图片查看器实现方法,具体如下: main.xml部分代码如下: <?xml version="1.0" encoding ...
- amazeui中的js插件有哪些(详解功能)
amazeui中的js插件有哪些(详解功能) 一.总结 一句话总结: 二.amazeui中的js插件有哪些 1.UI 增强 警告框Alert 按钮交互Button 折叠面板Collapse 下拉组件D ...
- Hibernate中的配置文件
Hibernate中配置文件 主配置文件 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE h ...
- Swift API设计原则
注: 本文摘自 Swift API设计指南 一.基本原则 通俗易懂的API是设计者最重要的目标.实体.变量.函数等都具有一次申明.重复使用的性质,所以一个好的API设计,应该能够使用少量的解读和示例就 ...
- Vue中v-for不绑定key会怎样
Vue的v-for不绑定key,默认行为和绑定key="index"是差不多的,官方没有默认这种行为的情况下,会导致所有列表DOM重新渲染.key="index" ...
- Android Studio中创建java项目
1.创建普通的android工程 2.创建一个module 3.module类型选择java library 4.填写libary和class的名字 5.生成的工程如图所示 6.然后点击Run --- ...
- MySQL日期 专题
一.MySQL 获得当前日期时间 函数 1.1 获得当前日期+时间(date + time)函数:now() mysql> select now();+--------------------- ...