JDK8集合类源码解析 - LinkedList
linkedList主要要注意以下几点:
1构造器
2 添加add(E e)
3 获取get(int index)
4 删除 remove(E e),remove(int index)
5 判断对象是否存在:contain(E e)
Jdk8中的linkedList基于双向链表来实现的
双向链表每个结点包含数据域,一个前指针和一个后指针,分别指向前驱结点和后继结点(如果有前驱/后继的话,没有就是null)。
另外,双向链表还有一个first指针,指向头节点,和last指针,指向尾节点。
接下来我们来看看源码
transient int size = 0;
transient Node<E> first; //整个链表的头结点
transient Node<E> last; //整个链表的尾结点
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;
}
}
如图所示

1构造器
有两个构造器,分别是空的和从一个集合创建。

注意:因为基于链表创建,理论上无容量的限制,不需要扩容的操作。
2 添加add(E e)
默认添加是在链表尾部添加
public boolean add(E e) {
linkLast(e);
return true;
}
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; //把当前结点设为头结点
else //不为空
l.next = newNode; //把当前结点设为尾结点的后继
size++;
modCount++;
}
3 获取get(int index)
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
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;
}
}
注意:1跟arraylist不同的是,linkedlist查找指定下标元素需要遍历
2 >> 1 (除以2) <<1 (乘以2)
4 删除 remove(E e),remove(int index)
public boolean remove(Object o) {
if (o == null) {
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null) { //先溢出第一个null
unlink(x);
return true;
}
}
} else {
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item)) { //找到了就移除
unlink(x);
return true;
}
}
}
return false;
}
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;
}
5 判断对象是否存在:contain(E e)
public boolean contains(Object o) {
return indexOf(o) != -1;
}
public int indexOf(Object o) {
int index = 0;
if (o == null) {
//从头开始找 找到第一个null
for (Node<E> x = first; x != null; x = x.next) {
if (x.item == null)
return index;
index++;
}
} else {
//从头开始找 看有没有等于item的
for (Node<E> x = first; x != null; x = x.next) {
if (o.equals(x.item))
return index;
index++;
}
}
return -1;
}
总结:1 Jdk8中的linkedList基于双向链表来实现的,插入删除快,查询慢,适合读少写多的情况
2 linkedList还有一些有趣的方法,可以实现队列
3添加元素时不用扩容
4 线程不安全
JDK8集合类源码解析 - LinkedList的更多相关文章
- JDK8集合类源码解析 - HashSet
HashSet 特点:不允许放入重复元素 查看源码,发现HashSet是基于HashMap来实现的,对HashMap做了一次“封装”. private transient HashMap<E,O ...
- JDK8集合类源码解析 - HashMap
java为数据结构中的映射定义了一个接口java.util.Map,此接口主要有四个常用的实现类,分别是HashMap.Hashtable.LinkedHashMap和TreeMap HashMap ...
- JDK8集合类源码解析 - ArrayList
ArrayList主要要注意以下几点: 1构造方法 2添加add(E e) 3 获取 get(int index) 4 删除 remove(int index) , remove(Objec ...
- Java集合类源码解析:Vector
[学习笔记]转载 Java集合类源码解析:Vector 引言 之前的文章我们学习了一个集合类 ArrayList,今天讲它的一个兄弟 Vector.为什么说是它兄弟呢?因为从容器的构造来说,Vec ...
- Java集合类源码解析:HashMap (基于JDK1.8)
目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...
- 从源码解析LinkedList集合
上篇文章我们介绍了ArrayList类的基本的使用及其内部的一些方法的实现原理,但是这种集合类型虽然可以随机访问数据,但是如果需要删除中间的元素就需要移动一半的元素的位置,效率低下.并且它内 ...
- Java集合类源码解析:ArrayList
目录 前言 源码解析 基本成员变量 添加元素 查询元素 修改元素 删除元素 为什么用 "transient" 修饰数组变量 总结 前言 今天学习一个Java集合类使用最多的类 Ar ...
- Java集合类源码解析:AbstractMap
目录 引言 源码解析 抽象函数entrySet() 两个集合视图 操作方法 两个子类 参考: 引言 今天学习一个Java集合的一个抽象类 AbstractMap ,AbstractMap 是Map接口 ...
- Java集合类源码解析:LinkedHashMap
前言 今天继续学习关于Map家族的另一个类 LinkedHashMap .先说明一下,LinkedHashMap 是继承于 HashMap 的,所以本文只针对 LinkedHashMap 的特性学习, ...
随机推荐
- elastic search 查询
eelastic search主要有两种查询方式,一种是查询字符串,一种是请求体(json格式)查询. 查询字符串: 查询字符串的功能相对简单,使用容易. 比如GET http://localhost ...
- oracle数据库连接不上
Oracle数据库1521端口telnet不通 现象:服务器的ip地址可以ping通,但是安装oracle过程中的指定的“1521”端口telnet不通过 解决办法:1.确保防火墙对1521端口开启: ...
- python数据分析之matplotlib学习
本文作为学习过程中对matplotlib一些常用知识点的整理,方便查找. 类MATLAB API 最简单的入门是从类 MATLAB API 开始,它被设计成兼容 MATLAB 绘图函数. from p ...
- c# double 类型保留几位小数
C 或 c :货币 D 或 d:十进制数 E 或 e:科学记数法(指数) F 或 f:定点 G 或 g:常规 N 或 n:数字 P 或 p:百分比 double.ToString("Nx & ...
- TZOJ 2722 Matrix(树状数组区间取反单点查询)
描述 Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row ...
- TZOJ 3244 Happy YuYu's Birthday(数学几何)
描述 9月10日教师节,也是YuYu的生日,妈妈给YuYu准备了一个很大的圆形蛋糕,YuYu看中了蛋糕中间那诱人的樱桃(都挤到一块啦),小家伙很高兴,心里开始盘算着如何将樱桃全部分给自己.YuYu是个 ...
- width多少,超过了用....表示
maxWidth:'140px',whiteSpace:'nowrap',overflow:'hidden',textOverflow:'ellipsis'
- 一、MySQL的连接建立与权限
一.MySQL的连接建立与权限 写这些的目的一是记录下工作这几年所学,算是成长脚印吧.二是复习一遍,也给自己当笔记看,通篇观点都属于个人理解较多.读者观看的时候也需要自己判断下是否正确,另外,记下一段 ...
- python 3.6.5 hashlib 和 hmac 模块
import hashlib m=hashlib.md5()# m=hashlib.sha256() m.update('hello'.encode('utf8'))print(m.hexdigest ...
- 当时钟事件声明为过程变量 让system.threading.timer时钟失效
这个项目的小模块就是画label 控件到tablepayoutpanel表单 之中, 中间用到了时钟,事件(带返回值的),哈希表 .由于时钟定义在 form1的启动构造函数中导致了form1,启动完毕 ...