从面试角度分析LinkedList源码
点击上方蓝色“方志朋”,选择“设为星标”
回复“666”获取独家整理的学习资料!
注:本系列文章中用到的jdk版本均为
java8
LinkedList
类图如下:
LinkedList
底层是由双向链表实现的。链表好比火车,每节车厢包含了车厢和连接下一节车厢的连接点。而双向链表的每个节点不仅有指向下一个节点的指针,还有指向上一个节点的指针。
在LinkedList
源码中有一个Node
静态类,源码如下:
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;}
}
一个Node
节点包含三个部分,分别是
item:数据
next:下一个节点的指针
prev:上一个节点的指针
LinkedList
的主要变量如下:
// 集合中的元素数量
transient int size = 0;/*** 首节点的指针.* Invariant: (first == null && last == null) ||* (first.prev == null && first.item != null)*/
transient Node<E> first;/*** 尾结点的指针.* Invariant: (first == null && last == null) ||* (last.next == null && last.item != null)*/
transient Node<E> last;
一、添加元素
LinkedList
支持在任意节点位置添加元素,不仅提供了集合常用的add()
方法,还提供了addFirst()
和addLast()
,add()
方法默认调用addLast()
方法,也就是默认是往链表尾部插入元素的。
add()
方法源码:
public boolean add(E e) {linkLast(e);return true;
}
1.1 尾部插入元素
linkLast()
源码如下:
void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;modCount++;
}
我们来画张图演示一下如何给链表尾部插入元素:
假如链表中没有元素
对应源码中的if语句
,如果没有元素则新增的这个节点为链表中唯一的一个元素,既是首节点,又是尾结点,前一个元素的指针和后一个元素的指针都是null。这里注意head
节点不是第一个节点,head
节点只是标识了这个链表的地址。
假如链表中有元素
对应源码中else语句
。先将新增的元素当成Last
节点,然后将原来的Last
节点的next
指向新节点。
elsel.next = newNode;
一图胜前言,画个图是不是什么都明白了。
1.2 头部插入元素
linkFirst()
源码如下:
private void linkFirst(E e) {final Node<E> f = first;final Node<E> newNode = new Node<>(null, e, f);first = newNode;if (f == null)last = newNode;elsef.prev = newNode;size++;modCount++;
}
还是根据上面的图来解读一下源码,先将第一个节点赋值给中间变量f
,将新节点newNode
赋值给first
节点。如果链表没有元素,则Last
节点和First
节点都是新插入的节点newNode
,否则,将原来的First
节点的头指针指向新节点。
二、删除元素
LinkedList
提供的删除方法有根据索引
和元素
删除,除此之外还提供删除第一个元素和最后一个元素的方法,这里我们只分析一下根据索引删除的方法。
public E remove(int index) {checkElementIndex(index);return unlink(node(index));
}
checkElementIndex(index)
方法就是用来判断传输的索引值是否合法,不合法则抛出数组越界异常。重点来看一下unlink(node(index))
方法是如何删除元素的。
node(index)
方法源码:
node(index)
方法就是根据索引获取该索引位置的节点
Node<E> node(int index) {// assert isElementIndex(index);// 如果指定下标 < 一半元素数量,则从首结点开始遍历// 否则,从尾结点开始遍历if (index < (size >> 1)) {Node<E> x = first;for (int i = 0; i < index; i++)x = x.next;return x;} else {Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}
}
unlink(Node<E> x)
源码如下:
E unlink(Node<E> x) {// assert x != null;final E element = x.item;final Node<E> next = x.next;final Node<E> prev = x.prev;if (prev == null) {first = next;} else {prev.next = next;x.prev = null;}if (next == null) {last = prev;} else {next.prev = prev;x.next = null;}x.item = null;size--;modCount++;return element;
}
画张图分析一下删除是如何进行的:
假设删除的是第一个元素:则它的
prev==NULL
,我们需要将他的后一个元素(图中的second)作为第一个元素假设删除的是最后一个元素,则它的
next==null
,我们需要将他的前一个元素(图中的second)作为最后一个元素如果是中间的任意元素,则需要将它的前一个元素的
next
指针指向它的后一个元素,同时将它的后一个元素的prev
指针指向它的前一个元素。
三、总结
LinkedList
底层是由双向链表实现的,由于是链表实现的,不仅要存放数据,还要存放指针,所以内存开销要比ArrayList
大,删除元素不需要移动其他元素,只需要改变指针的指向,因此删除效率更高,同时它没有实现RandomAccess
接口,因此使用迭代器遍历要比for循环更加高效。LinkedList
也支持插入重复值和空值,同样也是线程不安全的。
热门内容:
IntelliJ IDEA 2020.3 重大特性
用了3年CAT,这次我想选择SkyWalking,老板反手就是一个赞!
面试官:String长度有限制吗?是多少?
工作10年后,再看String s = new String("xyz") 创建了几个对象?
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。
明天见(。・ω・。)ノ♡
从面试角度分析LinkedList源码相关推荐
- 从面试角度分析CopyOnWriteArrayList源码
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 注:本系列文章中用到的jdk版本均为java8 相比很多同 ...
- 从面试角度分析ArrayList源码
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 注:本系列文章中用到的jdk版本均为java8 Array ...
- Java集合(二二): LinkedList源码剖析
目录 1.LinkedList简介 2.LinkedList数据结构 3.ArrayList源码分析LinkedList3.ArrayList源码分析 3.1 ArrayList继承结构和层次关系Li ...
- LinkedList 源码分析
前言 上篇文章分析了 ArrayList 的源码,面试过程中经常会被面试官来问 LinkedList 和 ArrayList 的区别,这篇文章从源码的角度来看下 LinkedList 以后,再和上篇文 ...
- 面试官系统精讲Java源码及大厂真题 - 06 LinkedList 源码解析
06 LinkedList 源码解析 智慧,不是死的默念,而是生的沉思. --斯宾诺莎 引导语 LinkedList 适用于集合元素先入先出和先入后出的场景,在队列源码中被频繁使用,面试也经常问到,本 ...
- java linkedlist源码_Java集合之LinkedList源码分析
一.LinkedList简介 LinkedList是一种可以在任何位置进行高效地插入和移除操作的有序序列,它是基于双向链表实现的. ps:这里有一个问题,就是关于实现LinkedList的数据结构是否 ...
- Java类集框架 —— LinkedList源码分析
在JDK1.7之前,LinkedList是采用双向环形链表来实现的,在1.7及之后,Oracle将LinkedList做了优化,将环形链表改成了线性链表.本文对于LinkedList的源码分析基于JD ...
- List接口的常用方法以及ArrayList/LinkedList源码分析
1.List接口的常用方法 ArrayList list = new ArrayList();list.add(123);list.add(456);list.add("AA"); ...
- 数组、链表、LinkedList源码分析、跳表
一.数组 1.什么是数组 数组是一种线性表数据结构,它用一组连续的内存空间,来存储一组具有相同类型的数据 线性表:数据排成像一条线一样的结构.每个线性表上的数据最多只有前和后两个方向.其实除了数组,链 ...
最新文章
- 在移动端禁用长按选中文本功能
- Redis常用命令入门5:有序集合类型
- mysql缺少函数_Sqlserver的窗口函数的精彩应用之数据差距与数据岛-答案篇
- PMP敏捷图表之价值流程图
- LeetCode Hot100 ---- 滑动窗口专题
- 常用内存分配函数的说明
- Java 命令行运行参数大全
- influxDB框架 数据存储 TSM 数据操作等详解
- springboot2源码2-SpringApplication运行
- c语言给一个函数添加功能,【C语言】请编写实现以下功能函数:实现对一个8bit数据(unsigned char)的指定位(例如第8位)的置0或置1操作,并保持其他位不变...
- 在ubuntu中安装PhantomJS
- NS3网络仿真(6): 总线型网络
- 【翻译】Windows下文件的命名
- 插入排序InsertSort
- SpringBoot整合editormd富文本编辑器
- 固体发动机内弹道matlab,固体火箭发动机内弹道性能的仿真研究
- 数据库身份证号用什么类型_数据库设计规范
- OpenStack排错记录---ResourceProviderCreationFailed和You are not authorized to perform the requested actio
- 如何在低代码开发平台上,实施表单设计流程
- 2019/2/13打印华氏温度与摄氏温度对照表