LinkedList是一個線性的,以雙向鏈表形式實現的有序性的集合,由於是鏈表實現,因此執行添加和刪除操做時效率比較高,執行查詢操做時效率比較低。bash
public LinkedList() {
}
複製代碼
當不傳入參數時,會建立一個空的LinkedListui
list.add("aaa");
複製代碼
當第一次調用add()
方法時,點擊add()
顯示以下內容spa
public boolean add(E e) {
linkLast(e);
return true;
}
複製代碼
在添加方法的內部會調用linkLast
方法,再點進去code
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<E> l = last
,其中last是transient Node<E> last;
,下一個語句是包含前驅l
和元素自己e
以及後繼null
的Node
類型的節點賦值給newNode
節點,再將newNode
賦給last
及first
。這就至關於cdn
size
進行維護
list.add("aaa");
list.addFirst("hello");
複製代碼
點擊進入會發現blog
public void addFirst(E e) {
linkFirst(e);
}
複製代碼
再點擊linkFirst
element
private void linkFirst(E e) {
final Node<E> f = first;
final Node<E> newNode = new Node<>(null, e, f);
first = newNode;
if (f == null)
last = newNode;
else
f.prev = newNode;
size++;
modCount++;
}
複製代碼
先是將transient Node<E> first;
賦值給f
,由於前面添加了元素aaa
,因此f
會指向aaa
節點。再將前驅爲null
元素值爲e
後繼爲f
的節點Node
賦值給newNode
,再將newNode
賦值給first
,此時first
和last
已經不指向相同的元素了,再將f
的前驅指向newNode
,隨着方法的結束f
和newNode
也會隨之失效,最終的效果會是這樣。rem
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
複製代碼
點擊addLast
string
public void addLast(E e) {
linkLast(e);
}
複製代碼
再點擊linkLast
it
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
賦值給l
,再將前驅爲l
元素值爲e
後繼爲null
的節點賦值給newNode
,這時newNode
爲最後一個元素並將本身與前一個元素相連,由於前面已經添加了兩個元素因此l==null
不成立,因此會將l
的後繼指向newNode
,隨着方法的結束l和newNode
也會消失。最終結果會是這樣
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
list.removeFirst();
複製代碼
點擊removeFirst
public E removeFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return unlinkFirst(f);
}
複製代碼
首先會將first
保存在節點f
中,再點擊unlinkFirst
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
複製代碼
先會將節點f
的元素值和f
的後繼保存,再將元素自己和後繼設置爲null
,由於前面添加了三個元素,因此next==null
不成立,就會將待刪除元素下一個節點的前驅設置爲空。最後將保存的元素返回。
list.add("aaa");
list.addFirst("hello");
list.addLast("world");
list.removeFirst();
list.removeLast();
複製代碼
點擊removeLast
public E removeLast() {
final Node<E> l = last;
if (l == null)
throw new NoSuchElementException();
return unlinkLast(l);
}
複製代碼
先將last
節點保存,點擊unlinkLast
private E unlinkLast(Node<E> l) {
// assert l == last && l != null;
final E element = l.item;
final Node<E> prev = l.prev;
l.item = null;
l.prev = null; // help GC
last = prev;
if (prev == null)
first = null;
else
prev.next = null;
size--;
modCount++;
return element;
}
複製代碼
將節點的元素值和元素的前驅進行保存,再將節點自己和前驅設置爲null
,由於前面有元素因此前驅不爲空,因此會將本身的前一個元素的後繼設置爲空,這樣就與上一個元素斷開了鏈接,最後將保存的元素返回。