一、概述
LinkedList底层数据结构是基于双向链表实现的,实现了List,和ArrayList一样元素顺序和插入顺序保持一致,不过由于是链表实现,本身是无容量限制的,所以没有初始容量设置也没有扩容需求。
public class LinkedList
extends AbstractSequentialList
implements List, Deque, Cloneable, java.io.Serializable
{
transient int size = 0;
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node first;
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node last;
Node节点如下:
private static class Node {
E item;
Node next;
Node prev;
Node(Node prev, E element, Node next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
由上可以看到,每个节点包含了前后指针实现双向链表,同时LinkedList保留了first、last头指针和尾指针。为何size、first、last都要transient修饰我暂时还没悟透,等后续补上。LinkedList不擅长随机访问,对于set(i)、get(i)需要从头遍历(如果i大于size的一半则从尾遍历)
二、主要实现
1、构造函数
1)、LinkedList():构造空list;
2)、LinkedList(Collection extends E> c):构造一个包含c中元素的LinkedList,可以看出构建的链表是双向的
/**
* Constructs an empty list.
*/
public LinkedList() {
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public LinkedList(Collection extends E> c) {
this();
addAll(c);
}
public boolean addAll(Collection extends E> c) {
return addAll(size, 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;
//succ是插入位置的节点,pred是前一个节点
Node 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 newNode = new Node<>(pred, e, null);//构造一新节点,设置pred,next在下次循环中设置
//此处主要是前一个对象的next
if (pred == null)
first = newNode;
else
pred.next = newNode;//代表上一个节点的next
pred = newNode;
}
if (succ == null) {
last = pred;
} else {
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++;
return true;
}
/**
* Returns the (non-null) Node at the specified element index.
*/
Node node(int index) {
// assert isElementIndex(index);
//遍历链表的方向,小于一半的从first往后遍历,否则从last往前遍历
if (index < (size >> 1)) {
Node x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
Node x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
2、新增
新增的相关方法有多个,由于篇幅有限,就只分析add(int index, E element)
public void add(int index, E element) {
checkPositionIndex(index);
if (index == size)
//这个比较简单,就是在链表尾部新增一个元素
linkLast(element);
else
//在index处插入element
linkBefore(element, node(index));
}
/**
* Links e as last element.
*/
void linkLast(E e) {
final Node l = last;
final Node newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
/**
* Inserts element e before non-null Node succ.
*/
void linkBefore(E e, Node succ) {
// assert succ != null;
final Node pred = succ.prev;
final Node newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
add(int index, E element):在此列表中指定的位置插入指定的元素。
addAll(Collection extends E> c):添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。
addAll(int index, Collection extends E> c):将指定 collection 中的所有元素从指定位置开始插入此列表。
AddFirst(E e): 将指定元素插入此列表的开头。
addLast(E e): 将指定元素添加到此列表的结尾。
2、删除
同样,由于篇幅有限,仅介绍下remove(int index),关键代码是unlink(),代码逻辑很清晰,并无难懂之处
public E remove(int index) {
checkElementIndex(index);
return unlink(node(index));
}
/**
* Unlinks non-null node x.
*/
E unlink(Node x) {
// assert x != null;
final E element = x.item;
final Node next = x.next;
final Node 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;
}
clear(): 从此列表中移除所有元素。
remove():获取并移除此列表的头(第一个元素)。
remove(int index):移除此列表中指定位置处的元素。
remove(Objec o):从此列表中移除首次出现的指定元素(如果存在)。
removeFirst():移除并返回此列表的第一个元素。
removeFirstOccurrence(Object o):从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
removeLast():移除并返回此列表的最后一个元素。
removeLastOccurrence(Object o):从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。