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 的特性学习, ...
随机推荐
- CSS实现禁止文字选中
E10平台预览第四版中包含了对 CSS3 新属性 -ms-user-select 的支持,Web 开发人员可以利用这一新属性轻松精确的控制用户可以在网站上选择哪些文本. user-select:non ...
- Python 面向对象基础(类、实例、方法、属性封装)
python是面向对象语言,一切皆对象. 面向过程: 变量和函数. “散落” 在文件的各个位置,甚至是不同文件中.看不出变量与函数的相关性,非常不利于维护,设计模式不清晰. 经常导致程序员,忘记某个变 ...
- Pandas文本操作之读取操作
读写文本格式的数据 pandas中的解析函数 函数 说明 read_csv 从文件.url.文件型对象中加载带分隔符的数据,默认分隔符为逗号 read_table 从文件.url.文件型对象中加载带分 ...
- tight
tight - 必应词典 美[taɪt]英[taɪt] adv.紧紧地:牢固地 adj.牢固的:紧的:不松动的:难解开的 n.紧身衣 网络紧身的:紧密的:密封的 变形比较级:tighter:最高级:t ...
- http://www.bugku.com:Bugku——SQL注入1(http://103.238.227.13:10087/)
Bugku——SQL注入1(http://103.238.227.13:10087/) 过滤了几乎所有的关键字,尝试绕过无果之后发现,下面有个xss过滤代码.经搜索得该函数会去掉所有的html标签,所 ...
- Adb logcat 抓日志
http://blog.csdn.net/hujiachun1234/article/details/43271149 http://www.cnblogs.com/medsonk/p/6344373 ...
- 微信小程序template模板与component组件的区别和使用
前言: 除了component,微信小程序中还有另一种组件化你的方式template模板,这两者之间的区别是,template主要是展示,方法则需要在调用的页面中定义.而component组件则有自己 ...
- TZOJ 4325 RMQ with Shifts(线段树查询最小,暴力更新)
描述 In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each que ...
- xadmin系列之单实例模式
先看下单实例的定义 python的模块实现单例模式是python语言特有的,python的模块天然就是单例的,因为python有个pyc文件,导入一次后,第二次导入直接从pyc中取数据了 这里我们主要 ...
- echarts柱状图Demo
echarts链接:http://gallery.echartsjs.com/editor.html?c=xB1Sfo5JbX 代码: var xData = ['a', 'b', 'c', 'd', ...