LinkedList的實現其實是一個帶啞前端節點的雙向迴圈鏈表。
1.LinkedList的欄位
private transient Entry<E> header = new Entry<E>(null, null, null);
//Entry是一個LinkedList的內部類,其實就是鏈表上的節點,包含兩個指標,一個指向
//前面節點,一個指向後面節點
private static class Entry<E> {
E element;
Entry<E> next;
Entry<E> previous;
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}
//LinkedList中元素的數量
private transient int size = 0;
最後還有一個繼承來的modCount欄位。
2.構造方法
/**
* 預設設定啞前端節點,其next和previous引用都指向它自己。形成了迴圈鏈表
*/
public LinkedList() {
header.next = header.previous = header;
}
3.核心方法:
(1) addBefore方法
//在指定節點前面增加一個節點
private Entry<E> addBefore(E e, Entry<E> entry) {
//首先構建一個新的Entry節點,其next引用指向指定的節點entry,其
//previous引用指定節點原來的前面的節點
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
//調整newEntry的前面節點的next引用指向newEntry
newEntry.previous.next = newEntry;
//調整newEntry的後面節點的previous引用指向newEntry
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}
(2)entry方法
/**
* 得到執行索引位置的節點,如果索引位置在前一半,則從前面開始尋找,
若索引位置在後一半,則從後面位置開始尋找。
*/
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
if (index < (size >> 1)) { //size>>1等效於size/2,但是移位元運算
//效率更高
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}
4.有了上面的兩個核心方法,增加和刪除的方法主要以這兩個方法為基礎的。
例如,
(1)
public void add(int index, E element) {
//如果在最後增加一個元素,就指定的節點就是啞前端節點,由於是迴圈鏈表,
//在最後增加一個元素,它的後面的元素當然是前端節點了。如果索引位置不是
//在最後,則先用entry方法得到指定索引位置的元素。之後再調用addBefore
//方法。
addBefore(element, (index==size ? header : entry(index)));
}
(2)
//刪除指定索引位置的元素,也是先調用entry方法得到相應的元素,再進行刪除操作。
public E remove(int index) {
return remove(entry(index));
}
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();
E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}
5.其他方法
(1)
//刪除一個對象,分對應的引用o是null還是非null兩種情況。
public boolean remove(Object o) {
if (o==null) {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
remove(e);
return true;
}
}
} else {
for (Entry<E> e = header.next; e != header; e = e.next) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}
(2)
//尋找元素o,也是分o為null和非null兩種情況,但是不管是哪一種情況,都是順序尋找
public int indexOf(Object o) {
int index = 0;
if (o==null) {
for (Entry e = header.next; e != header; e = e.next) {
if (e.element==null)
return index;
index++;
}
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}
6. 由於LinkedList實現了雙端隊列Deque這個介面,因此,也具有雙端隊列操作的相關方法。因此,LinkedList可以當作先進先出的隊列使用,也可以當作先進後出的堆棧使用。
7. LinkedList實現了迭代器
但是,這個迭代器的是實現ListIterator介面的,也就是說,可以向前或者向後進行迭代。
Come from:http://jimmee.javaeye.com/blog/607891