public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable
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; } }
transient Node<E> first; transient Node<E> last;
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);//創建節點對象,前一個(perv屬性)是last,後一個(next屬性)是null,中間item數據是輸入的參數e last = newNode; if (l == null) first = newNode; //若是最後一個節點 爲null表示鏈表爲空,則添加數據時將新加的數據做爲第一個節點 else l.next = newNode; //若是鏈表不爲空則將最後一個鏈表的next屬性指向新添加的節點 size++; //鏈表長度自增1 modCount++; } 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; } }
public boolean addAll(int index, Collection<? extends E> c) { checkPositionIndex(index);//判斷index是否越界,越界則拋出異常 Object[] a = c.toArray(); int numNew = a.length;//要插入的集合的長度 if (numNew == 0) return false; Node<E> pred, succ;//聲明pred和succ兩個Node對象,用於標識要插入元素的前一個節點和最後一個節點 if (index == size) { //若是size等於原數組長度則表示在結尾添加 succ = null; pred = last; } else { succ = node(index);//index位置上的Node對象 pred = succ.prev; } for (Object o : a) { //遍歷要插入的集合 @SuppressWarnings("unchecked") E e = (E) o; Node<E> newNode = new Node<>(pred, e, null); if (pred == null) first = newNode; //若是要插入的位置的前一個節點爲null表示是第一個節點,則直接將newNode賦給第一個節點 else pred.next = newNode; //將要插入的集合元素節點對象賦給此位置原節點對象的前一個對象的後一個,即更改前一個節點對象的next指針指到新插入的節點上 pred = newNode;//更改指向後將新節點對象賦給pred做爲下次循環中新插入節點的前一個對象節點,依次循環 } //此時pred表明集合元素的插入完後的最後一個節點對象 if (succ == null) { //結尾添加的話在添加完集合元素後將最後一個集合的節點對象pred做爲last last = pred; } else { pred.next = succ;//將集合元素的最後一個節點對象的next指針指向原index位置上的Node對象 succ.prev = pred;//將原index位置上的pred指針對象指向集合的最後一個對象 } size += numNew; modCount++; return true; } Node<E> node(int index) { if (index < (size >> 1)) { //判斷index是否小於size的一半,若是小於則從頭遍歷節點,不然從結尾遍歷節點 Node<E> x = first; for (int i = 0; i < index; i++) x = x.next; //從first第一個節點開始,依次將後一個節點賦給x return x; //返回index位置上的Node對象,下同理 } else { Node<E> x = last; for (int i = size - 1; i > index; i--) x = x.prev; return x; } }
public E remove(int index) { checkElementIndex(index); return unlink(node(index)); } E unlink(Node<E> x) { final E element = x.item; final Node<E> next = x.next; final Node<E> prev = x.prev; if (prev == null) { first = next; } else { prev.next = next;//將傳入的節點的下一個節點對象賦給其以前前一個節點的下一個節點對象,即將傳入的節點對象跳過 x.prev = null;//將傳入對象的前一個節點對象置空使其前一個指針不指向任何元素 } if (next == null) { last = prev;//若是next爲null表示是最後一個元素,直接將pred節點賦給last } else { next.prev = prev; x.next = null;//將傳入節點的後一個節點置空,使其後一個節點指針不指向任何元素 } x.item = null;//將傳入的節點對象上的對象置空,也就是整個Node對象中的屬性都爲空了,後面會被GC回收 size--; modCount++; return element; }
public E set(int index, E element) { checkElementIndex(index);//檢查索引越界狀況 Node<E> x = node(index);//獲取index位置上的節點對象 E oldVal = x.item; x.item = element;//將新插入的元素直接賦給此位置上節點對象的item屬性便可 return oldVal; }
public E get(int index) { checkElementIndex(index);//檢查索引越界狀況 return node(index).item;//返回該index位置上的節點對象的item屬性,即該位置上的實際值 }