雙向鏈表結構
LinkedList作爲java又一大常用集合,其內部也有許多特性需要關注,首先我們從源碼可以剖析出LinkedList爲一個雙向鏈表結構,如下圖:
具體源碼分析如下:
首先是LinkedList裏的重要屬性:
//鏈表首指針
transient Node<E> first;
//鏈表尾指針
transient Node<E> last;
LinkedList的默認構造器爲一個空構造器:
/**
* Constructs an empty list.
*/
public LinkedList() {
}
下面來看看linkedlist的add方法:
public boolean add(E e) {
linkLast(e);
return true;
}
void linkLast(E e) {
//獲取尾指針
final Node<E> l = last;
//新建節點,將新節點的前驅指針指向尾指針
final Node<E> newNode = new Node<>(l, e, null);
//尾指針等於新建節點
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
//Node爲LinkdList的靜態內部類
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中還有一個重要的get方法,通過雙向鏈表的特殊特性遍歷節點時無需遍歷全部節點即可找出所需節點:
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
關注node方法裏的算法:
Node<E> node(int index) {
// assert isElementIndex(index);
//判斷傳入的索引位置是否靠近最左端還是最右端
if (index < (size >> 1)) {
//靠近左端則用首指針遍歷
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
} else {
//靠近右端則用尾指針遍歷
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}