目录
1. LinkedList
概述
jdk 1.2
的时添加的集合类,底层使用了 双链表 实现的,能够从链表头部或尾部操作数据元素- 实现了
List
接口,因此也可以使用方法get(index)
访问元素,但是效率较低,因为get(index)
实际上都是从链表头部或尾部开始顺序遍历的 - 实现了
Cloneable, Serializable
标志性接口,支持克隆和序列化 - 是一个线程不安全的类
2. LinkedList
源码解读
如上图所示,
LinkedList
属于线性表的链式存储结构的实现(Vector
和 ArrayLsit
都是线性表的顺序存储结构的实现)
LinkedList
底层使用的双链表结构,外部保持有一个头节点(Node<E> first
)和一个尾节点(Node<E> last
)的引用- 双链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作
2.1. 主要类属性
// LinkedList中元素个数
transient int size = 0;
// 链表头节点
transient Node<E> first;
// 链表尾节点
transient Node<E> last;
头节点和尾节点的加入,让 LinkedList
可以从头节点添加,也可以从尾添加,也就是说可以作为先进先出(FIFO
)的队列,也可以作为后进先出(LIFO
)的栈
2.2. 数据结构(双链表)
=数据结构之链表:https://blog.csdn.net/weixin_38192427/article/details/116952311
- 不同于
ArrayList
的内部数组具有的天然顺序存储,双链表的实现需要记录某个元素的前驱者后继者,因此LinkedList
使用一个对象Node
来作为元素节点 Node
作为LinkedList
的核心,也就是LinkedList
中真正用来存储元素的数据结构。内部类Node
就是实际的节点对象,或者说每个节点存放一个Node
,用于存放实际元素的地方
private static class Node<E> {
// 数据域,实际存放的元素,节点的值
E item;
// 后继,储存下一个节点的引用
Node<E> next;
// 前驱,储存上一个节点的引用
Node<E> prev;
/**
* Node节点的构造函数
* @param prev 前驱,即上一个节点的引用
* @param element 存储的元素的值
* @param next 后继,即下一个节点的应用
*/
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
2.3. 构造器
2.3.1. LinkedList()
构造一个空列表,里面没有任何实现,仅仅只是将 header
节点的前一个元素、后一个元素都指向自身(null
)
public LinkedList() {
}
2.3.2. LinkedList(Collection<? extends E> c)
构造一个包含指定 collection
中的元素的列表,这些元素按其 collection
的迭代器返回的顺序排列
public LinkedList(Collection<? extends E> c) {
// 首先调用无参构造其,创建一个空列表
this();
// 调用 addAll方法
addAll(c);
}
2.4. 获取的方法
2.4.1. 获取头节点数据
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
2.4.2. 获取尾节点数据
public E getLast() {
final Node<E> l = last;
if