第一章分析的List的一种常见实现ArrayList,底层基于数组结构存储元素,这一章分析List的另一种实现,
基于链表结构的实现,也就是LinkedList.首先现分析源码,最后在比较这两者之间的差异。
1、jdk逻辑图
2、三个主要的成员变量:
transient int size = 0;
transient Node<E> first;
transient Node<E> last;
其中Class Node<E> 是LinkedList<E>的内部静态类,具体实现这样:
实际上就是一个双向链表结构。
3、LinkedList提供了两个构造器
1)无参构造器
2)入参为Collection类型的集合
核心添加元素的代码块
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); /**遍历返回index索引处的节点,此处用了二分法查找的技巧**/
pred = succ.prev;
}
/**遍历插入或追加元素**/
for (Object o : a) {
@SuppressWarnings(“unchecked”) E e = (E) o;
Node<E> newNode = new Node<>(pred, e, null); /** 新创建一个链表节点,newNode.prev->pred,newNode->next->null,newNode.item->e**/
if (pred == null) /**链表为空**/
first = newNode;
else /** 追加新的链表节点**/
pred.next = newNode;
pred = newNode;
}
if (succ == null) { /**last指向最后添加一个元素节点**/
last = pred;
} else { /**维护插入索引处节点与添加节点的指向关系**/
pred.next = succ;
succ.prev = pred;
}
size += numNew;
modCount++; /**fast-fail机制**/
return true;
}
4、重要方法分析(其实不太难)
1)添加元素
public boolean add(E e); /**添加一个元素到链表中去**/
public void add(int index, E element); /**在指定索引的处添加元素**/
public void addFirst(E e);
public void addLast(E e);
以上方法很简单不在分析,读者可以自己看源码。
2)删除元素
public E remove(); /**删除头结点**/
public E remove(int index);/**删除指定索引的元素**/
public boolean remove(Object o);/**删除指定对象**/
就拿 public E remove(int index);做一个简单的分析吧,
public E remove(int index) {
checkElementIndex(index); //检查索引的合法性
return unlink(node(index)); //移除指定的非null结点
}
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指向第二节点
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;
}