- LinkedList中數據的載體Node (托盤)
代碼實現:
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;
}
}
鏈表的這種托盤的結構決定了它的的特點:
- 數據的寫入很快,但是數據的讀取很慢。
- 數據沒有擴容的概念。
在鏈表中有兩個托盤:firstNode和lastNode。
transient Node<E> first;
transient Node<E> last;
在第一次添加元素時,新的元素既是firstNode也是lastNode,這點可以在源碼中體現。
- 鏈表中添加(add)方法解析
transient int size = 0;
public void add(int index, E element) {
checkPositionIndex(index);
//checkPositionIndex方法是用來檢測index是否在[0,size)中,在返回index,否則拋出
//IndexOutOfBoundsException異常。
if (index == size)
linkLast(element); //添加第一個元素
else
linkBefore(element, node(index)); //添加第N個元素。
}
在add方法中判斷是不是第一次添加,size在這裏的默認值爲0,當第一次添加是index爲0,執行linkLast方法。
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++;
}
/* 這裏的last變量是上文中的托盤 Node<E> last;
* l, e, null 變量的意思是上家,數據元素,下家,這裏下家爲null.
* 當l == null 時,設置first = newNode;這句話的意思就是
* 【在第一次添加是】新元素既是第一個也是最後一個。
*/
在這裏體現了第一個添加的元素既是FirstNode也是LastNode這句話。
而下面這句話 l.next = newNode 體現了鏈表每個托盤是雙向關聯的。
當我們添加的數據不是第一個是,就會執行linkBefore方法,但是在分析linkBefore方法之前,我們先來分析一下 Node<E> node(int index)
這個方法:
Node<E> node(int index) {
if (index < (size >> 1)) { //判斷index在前半段還是在後半段。
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;
}
}
這個方法是鏈表中的查詢方法,index在前半段時取出第一個托盤 Node<E> x = first ,往後查 x = x.next
當index在後半段時取出最後一個托盤 Node<E> x = last ,往前查 x = x.prev 。
當找到要插入的位置時,返回所在的托盤, linkBefore(E e, Node<E> succ)方法承接這個托盤,將新的數據插入到該節點之前。
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;
final Node<E> newNode = new Node<>(pred, e, succ);
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
/* 首先獲取succ的上家記做pred,將pred當做上家傳入新創建的托盤newNode中,將succ當做下家傳入
* newNode 中,最後形成 new Node<>(pred, e, succ)。
* 如果pred不存在,那就把NowNode設置爲firstNode。否則,將
* pred的下家設置爲newNode。
*/
以上總結是個人觀點,如有存在錯誤請指正。