LinkedList源碼分析

LinkedList源碼分析

LinkedList是一個雙向鏈表的數據結構實現。java

類的實現接口及繼承父類

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable

AbstractSequentiaList<E>

這個類提供了一個List接口實現,爲實現序列訪問的數據存儲結構提供了所須要的最小化接口實現。對於支持隨機訪問數據的List好比數組,應該優先使用AbstractList。node

List 接口

一個有序的集合。這個接口能夠精確控制每一個元素在列表中的位置插入。用戶能夠經過整數索引來訪問元素(位置在列表中)。數組

Deque

一個有序的集合支持在頭和尾進行插入和刪除元素。deque是 double ended queue (雙端隊列)的縮寫。
deque的大多實現元素數量是沒有大小限制的。但這個接口支持容量限制。微信

構造方法

public LinkedList() {
}


public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

第一個是一個空的構造器,第二個構造器調用了addAll()方法。數據結構

在研究addAll()方法以前,咱們先來看一下幾個重要的屬性。源碼分析

//容器的大小:
transient int size = 0;

//首節點:
transient Node<E> first;

//尾節點:
transient Node<E> last;



//節點數據結構
private static class Node<E> {
E item;//節點的值
Node<E> next;//節點的下一個節點 若是等於null 則爲尾節點
Node<E> prev;//節點的上一個節點,若是等於null則爲首節點

Node(Node<E> prev, E element, Node<E> next) {//構造器 構造節點
    this.item = element;
    this.next = next;
    this.prev = prev;
}
}

經常使用方法解析

linkFirst() 插入第一個節點

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++;//修改次數加一
}

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++;//修改次數加一
}

linkBefore(E e,Node<E> succ)

//插入節點e ,在不爲空的succ節點以前
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
final Node<E> pred = succ.prev;//succ的前一個節點
final Node<E> newNode = new Node<>(pred, e, succ);//構造新節點插入succ以前
succ.prev = newNode;//succ的前一個節點爲新構造的節點
if (pred == null)//若是succ的前一個節點爲空,則本次插入節點將作爲首節點
    first = newNode;
else
    pred.next = newNode;//不然新節點做爲succ的上一個節點
size++;//容器大小加一
modCount++;//修改次數加一
}

unlinkFirst(Node<E> f) f節點的下一個節點做爲首節點

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.next 釋放了內存,等待垃圾回收機制進行回收內存。this

//unlinkFirst方法被調用移除首節點
public E removeFirst() {
final Node<E> f = first;
if (f == null)
    throw new NoSuchElementException();
return unlinkFirst(f);
}

unlinkLast(Node<E> l) f節點的下一個節點做爲尾節點

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;
}



public E removeLast() {
final Node<E> l = last;
if (l == null)
    throw new NoSuchElementException();
return unlinkLast(l);
}

getFirst() 獲得首節點的值

public E getFirst() {
final Node<E> f = first;
if (f == null)
    throw new NoSuchElementException();
return f.item;
}

remove(Object o)

public boolean remove(Object o) {
if (o == null) {//若是被移除元素爲空
    for (Node<E> x = first; x != null; x = x.next) {
        if (x.item == null) {//判斷節點的值是否爲空
            unlink(x);//移除元素
            return true;
        }
    }
} else {
    for (Node<E> x = first; x != null; x = x.next) {
        if (o.equals(x.item)) {
            unlink(x);
            return true;
        }
    }
}
return false;
}

隊列操做

peek() 返回隊列首元素,不移除

public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}

poll() 返回隊列首元素,並移除隊列

public E poll() {
final Node<E> f = first;
return (f == null) ? null : unlinkFirst(f);
}

offer() 入隊 插入隊列尾

public boolean offer(E e) {
return add(e);
}

從poll和offer方法能夠看出Linked是一個FIFO先進先出隊列(first input first output )spa

node(int index) 索引查詢元素

//使用二分法用索引查找元素
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;
}

}code

關注個人公衆號第一時間閱讀有趣的技術故事
掃碼關注:

也能夠在微信搜索公衆號便可關注我:codexiulian
渴望與你一塊兒成長進步!繼承

相關文章
相關標籤/搜索