java集合: LinkedList原始碼淺析
阿新 • • 發佈:2018-12-06
LinkedList 資料結構是雙向連結串列,插入刪除比較方便。
LinkedList 是執行緒不安全的,允許元素為null 。
建構函式:
建構函式是空的。
/** * Constructs an empty list. */ public LinkedList() { }
基本屬性:
//transient表示不會被序列化 //集合元素數量 transient int size = 0; //連結串列頭節點 transient Node<E> first;//連結串列尾節點 transient Node<E> last;
連結串列節點: Node<E>
連結串列節點通過內部類Node<E>表示,這是一個雙向連結串列。
既可以從頭開始遍歷,也可以從尾開始遍歷。
next是上一個節點,prev是下一個節點。
private static class Node<E> {
//連結串列儲存的元素 E item; //next表示下一個節點 Node<E> next; //prev表示上一個節點 Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } }
新增元素: add()
/** * Appends the specified element to the end of this list. * * <p>This method is equivalent to {@link #addLast}. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#add}) */ publicboolean add(E e) { linkLast(e); return true; }
呼叫 linkLast()方法。在連結串列末尾新增新節點。
/** * Links e as last element. */ 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++; }
查詢連結串列: get(index)
使用get(int index)。如下:
/** * Returns the element at the specified position in this list. * * @param index index of the element to return * @return the element at the specified position in this list * @throws IndexOutOfBoundsException {@inheritDoc} */ public E get(int index) { //檢查下標,如果越界就拋異常 checkElementIndex(index); //遍歷雙向連結串列返回結果 return node(index).item; } private void checkElementIndex(int index) { if (!isElementIndex(index)) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /** * Tells if the argument is the index of an existing element. */ private boolean isElementIndex(int index) { return index >= 0 && index < size; }
遍歷連結串列: node(index)
在用get(index)查詢元素時呼叫了node(index)方法來遍歷。
如果下標小於連結串列長度的一半,就從頭遍歷。反之就從尾遍歷。這樣查詢的效率比較高。
/** * Returns the (non-null) Node at the specified element index. */ Node<E> node(int index) { // assert isElementIndex(index); // size右移1位,表示size的一半。 //如果下標小於連結串列長度的一半,就從頭開始遍歷。 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; } }
參考部落格 :