继承关系
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
- 首先继承了
AbstractSequentialList<E>该抽象类是抽象顺序访问的list,比如linkedList。为了减少重复代码。 - 实现了
List接口,可以作为一个list使用 - 实现
Deque,可以作为一个双端队列使用 - 实现
Cloneable,这是一个标记接口,说明LinkedList可以被克隆 - 实现
Serializable,标记接口,说明可LinkedList可被序列化
存储结构
//大小
transient int size = 0;
//链表头节点
transient Node<E> first;
//链表尾节点
transient Node<E> last;
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;
}
}
LinkedList的结构就是一个普通的双向链表
构造方法
public LinkedList()
//没什么好说的,因为空链表的时候都为null值,所以什么都不用做
//链表也没什么扩容的问题
//链表初始容量也不需要设置
public LinkedList() {
}
public LinkedList(Collection<? extends E> c)
//通过集合进行初始化,把集合全部添加到linkedList中
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}
//在索引index处添加集合c
public boolean addAll(int index, Collection<? extends E> c) {
checkPositionIndex(index);
//获取集合的数组
Object[] a = c.toArray();
int numNew = a.length;
if (numNew == 0)
return false;
Node<E> pred, succ;
if (index == size) {
succ = null;
pred = last;
} else {
succ = node(index);
pred = succ.prev;
}
//遍历输入集合所有元素
for (Object o : a) {
//创建新节点
@SuppressWarnings("unchecked") E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null);
//添加节点
if (pred == null)
first = newNode;
else
pred.next = newNode;
pred = newNode;
}
//连接
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
重要方法
add(E e)
//实现的是List<>的接口方法
public boolean add(E e) {
linkLast(e);
return true;
}
linkLast(E e)
void linkLast(E e) {
//保存旧的尾节点
final Node<E> l = last;
//创建节点,并把prev指向尾节点
final Node<E> newNode = new Node<>(l, e, null);
//更新尾节点为新节点
last = newNode;
//如果为空,新节点设置为头节点
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
get(int index)
public E get(int index) {
//检验index是否在[0-n)之间
checkElementIndex(index);
return node(index).item;
}
node(int index)
Node<E> node(int index) {
if (index < (size >> 1)) {
//index如果小于size一半,从头开始遍历
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//index如果大于size一半,从尾开始遍历
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
add(int index, E element)
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)、
//如果是添加到尾部,直接添加即可
linkLast(element);
else
//先获取需要插入的节点位置,然后调用linkBefore进行插入
linkBefore(element, node(index));
}
linkBefore(E e, Node node)
void linkBefore(E e, Node<E> succ) {
//暂存当前节点上一个节点
final Node<E> pred = succ.prev;
//创建新节点同时,将新节点的prev指向上一节点,next指向succ
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
//添加位置刚好是头节点,设置新头节点
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
先放这么多,其他就不放出来了。不过linkedList的代码还是非常简洁的,大佬不愧是大佬。