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虽然在设计上使用了抽象程度更高的流来作为文 ...
随机推荐
- [Compose] 11. Use Task for Asynchronous Actions
We refactor a standard node callback style workflow into a composed task-based workflow. For example ...
- Thinkphp5 Auth权限认证
Thinkphp5 Auth权限认证 一.总结 一句话总结:四表两组关系,一个多对多(权限和用户组之间),一个一对多(用户和用户组之间) 二.Thinkphp5 Auth权限认证 auth类在thin ...
- 我的IT成长路——为梦想扬帆起航
在持续了一个多月的雾霾之后,西安这座城市又看到了久违的阳光,好的天气预兆新梦想的开始.我的IT路从开始接触编程开始已经有5个年头了,从一个没有摸过计算机的农村男孩到现在学会几门编程语言的IT人,这段路 ...
- oracle中imp导入数据中文乱码问题(转)
(转自 http://blog.chinaunix.net/uid-186064-id-2823338.html) oracle中imp导入数据中文乱码问题 用imp命令向oracle中导入数据后, ...
- 【序列操作IV】树状数组套线段树/树套树
题目描述 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1 ...
- ServletContextListener和ContextLoaderListener的区别
ServletContext 被 Servlet 程序用来与 Web 容器通信.例如写日志,转发请求.每一个 Web 应用程序含有一个Context,被Web应用内的各个程序共享.因为Context可 ...
- Dictionary实现(收藏的)
源文献:https://www.cnblogs.com/InCerry/p/10325290.html 对于C#中的Dictionary类相信大家都不陌生,这是一个Collection(集合)类型,可 ...
- 聊聊QPS/TPS/并发量/系统吞吐量的概念
原文:聊聊QPS/TPS/并发量/系统吞吐量的概念 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/cainiao_user/article/deta ...
- asp.net中C#调用存储过程
创建存储过程: create procedure houseCount ( ), @house_count int output ) as select @house_count=COUNT(*) f ...
- RabbitMQ及其.NET客户端——几个小例子
一.简单生产者-消费者(使用direct交换器) 1.生产者 var factory = new ConnectionFactory();//实例化一个工厂 factory.HostName = &q ...