LinkedList 源码解析
LinkedList 简介
LinkedList是Java集合中的其中一种容器,底层是用双向链表来实现的,继承了AbstractSequentialList抽象类,实现了List, Deque, Cloneable, Serializable接口
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
LinkedList 构造函数
执行下列代码
List<String> list = new LinkedList();
解析LinkedList 构造函数
/**
* Constructs an empty list.
*/
public LinkedList() {
}
查看LinkedList的默认构造方法,什么都没有,只是基本的在堆内存中分配了空间;在继续查看其初始属性情况
/**
* 存储数据长度
*/
transient int size = 0;
/**
* 第一个元素
*/
transient Node<E> first;
/**
* 最后一个元素
*/
transient Node<E> last;
LinkedList 默认初始化的堆内存情况,如下图所示(图片来自[zhuanlan.zhihu.com/p/28101975]

其三个属性的初始情况是first,last都为null,而size是基础类型,初始化为0;
LinkedList add()方法
执行下列代码
List<String> list = new LinkedList();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
解析add()方法,查看源码
public boolean add(E e) {
linkLast(e);
return true;
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last; // 第一次添加,last = null,所以l = null
final Node<E> newNode = new Node<>(l, e, null); //初始化一个新的Node对象
last = newNode; // 把新的Node对象赋值给last
if (l == null)
first = newNode; // 把新Node对象赋值给first;这里last = first = newNode(意味着第一个和最后一个元素都指向同一个Node对象)
else
l.next = newNode;
size++; //数据长度+1
modCount++; // 修改次数+1
}
private static class Node<E> {
E item; //具体数据(李四)
Node<E> next; // 下一个元素引用地址(null)
Node<E> prev; // 上一个元素引用地址(null)
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
LinkedList 添加第一个元素的堆内存情况,如下图所示(图片来自[zhuanlan.zhihu.com/p/28101975]

/**
* Links e as last element.
*/
void linkLast(E e) {
final Node<E> l = last; // 第二次添加,last = 第一个元素(李四),所以l = 第一个元素(李四)
final Node<E> newNode = new Node<>(l, e, null); //初始化一个新的Node对象
last = newNode; // 把新的Node对象赋值给last
if (l == null) // 此时l不为空,为第一个元素(李四)
first = newNode;
else
l.next = newNode; // 第一个元素(李四)的下一个元素赋值为新的Node对象
size++; //数据长度+1
modCount++; // 修改次数+1
}
private static class Node<E> {
E item; //具体数据(王五)
Node<E> next; // 下一个元素引用地址(null)
Node<E> prev; // 上一个元素引用地址(李四)
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
LinkedList 添加第二个元素的堆内存情况,如下图所示(图片来自[zhuanlan.zhihu.com/p/28101975]


LinkedList 和 ArrayList的比较
- LinkedList:
- 底层采用的是双向链表的数据结构
- 查找数据时,需从头开始遍历,所以查找效率低,且不能随机访问
- 增删数据时,头数据的话,只需修改next属性,尾数据,只需修改prev属性,中间数据,两属性都修改,所以性能较高
- 线程不安全
- ArrayList:
- 底层采用的是数组的数据结构
- 查找数据时,可以访问数组下标,支持随机访问
- 增删数据时,找到删除数据下标位置,置为null之后,还需将后面的元素位置移至前面,所以性能相对较低
- 线程不安全