Java容器原始碼分析之LinkedList
阿新 • • 發佈:2020-11-06
LinkedList簡介
LinkedList是一個使用雙向連結串列結構實現的容器,與ArrayList一樣,它能動態擴充其長度,LinkedList相較於ArrayList,其任意位置插入速度比ArrayList要快,但是其查詢速度要比ArrayList要慢;LinkedList繼承自AbstractSequentialList,實現了List、Deque、Cloneable、Serializable介面。
LinkedList UML圖如下:
和ArrayList一樣,LinkedList也不是一個執行緒安全的容器。
LinkedList原始碼分析
構造方法
LinkedList有兩個構造方法:
public LinkedList() {
}
//從已有的一個容器建立一個LinkedList物件
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
addAll()方法:
public boolean addAll(Collection<? extends E> c) { return addAll(size, c); } public boolean addAll(int index, Collection<? extends E> c) { //檢查index是否溢位 checkPositionIndex(index); Object[] a = c.toArray(); int numNew = a.length; if (numNew == 0) return false; //獲取第index位置的node元素和node的前一個元素 //succ:第index位置的node元素 //pred:index位置前一個node元素 Node<E> pred, succ; if (index == size) { succ = null; pred = last; } else { succ = node(index); 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; else pred.next = newNode; pred = newNode; } if (succ == null) { last = pred; } else { pred.next = succ; succ.prev = pred; } size += numNew; modCount++; return true; }
add方法
LinkedList也有兩個add方法,如下:
public boolean add(E e) { //新增元素到隊尾 linkLast(e); return true; } public void add(int index, E element) { //檢查index是否溢位 checkPositionIndex(index); if (index == size) //index == size,直接新增到隊尾 linkLast(element); else //index != size,新增元素到index位置 linkBefore(element, node(index)); }
linkLast方法:
void linkLast(E e) {
final Node<E> l = last;
//新建一個node,將其前一個元素指標指向原連結串列的最後一個元素
final Node<E> newNode = new Node<>(l, e, null);
//更新尾指標
last = newNode;
if (l == null)
//若原last==null說明此時連結串列就一個元素
first = newNode;
else
//更新原連結串列尾元素指標
l.next = newNode;
size++;
modCount++;
}
linkBefore方法:
void linkBefore(E e, Node<E> succ) {
// assert succ != null;
//獲取指定位node元素的前一個元素pred
final Node<E> pred = succ.prev;
//新建一個node,將其前指標指向pred元素
final Node<E> newNode = new Node<>(pred, e, succ);
//將指定位置的node元素的前指標指向新元素,完成插入
succ.prev = newNode;
if (pred == null)
first = newNode;
else
pred.next = newNode;
size++;
modCount++;
}
獲取指定位置node指標方法node:
Node<E> node(int index) {
// assert isElementIndex(index);
//index > size/2時,說明在連結串列前半段,從前往後搜尋
if (index < (size >> 1)) {
Node<E> x = first;
for (int i = 0; i < index; i++)
x = x.next;
return x;
//index < size/2時,從後往前搜尋
} else {
Node<E> x = last;
for (int i = size - 1; i > index; i--)
x = x.prev;
return x;
}
}
get方法
public E get(int index) {
checkElementIndex(index);
return node(index).item;
}
get方法也比較簡單,首先檢測index是否溢位,然後直接找到index位置的元素,並返回其item。