JAVA ArrayList VS LinkedList 對比之一-背景調查

API 地址:http://docs.oracle.com/javase/6/docs/api/

涉及概念之間的關係如下:


圖解:

List 是一個接口,它繼承於Collection的接口。它代表着有序的隊列。它允許重複的元素。
AbstractList 是一個抽象類,它繼承於AbstractCollection。AbstractList實現List接口中除size()、get(int location)之外的函數。
AbstractSequentialList 是一個抽象類,它繼承於AbstractList。它的方法較少。專門爲LinkedList而設計。
ArrayList, LinkedList, Vector, Stack是List的4個實現類。

    ArrayList 通過一個Object[]數組存儲對象,要注意這個數組是transient類型的。它的add()和remove()方法是通過System.arraycopy(...)實現的,get()方法就是返回數組的一個元素。

    AbstractSequentialList 進一步地實現了add()、get()以及remove()方法。它通過調用ListIterator類中相應的方法實現這些方法。這樣的目的是通過雙向列表的特性,提高執行速度。它把listIterator(int index)方法聲明爲abstract類型,要求用戶必須重新實現。在添加和刪除元素時具有比ArrayList更好的性能.但在get與set方面弱於ArrayList。

    LinkedList 繼承自AbstractSequentialList,通過一個雙向鏈表存儲對象。注意這個鏈表的header是transient類型的。這裏的header中是不包含實際數據的,僅僅作爲鏈表的頭節點。它的add()、get()、remove()方法就是對雙向鏈表的操作。它通過雙向鏈表地特性,重新實現了listIterator(int index)方法,定義內嵌的ListIterator類。

ArrayList的源代碼:
    //size,isEmpty,get,set,iterator,和listIterator 等操作都是常量時間.add操作也接近常量時間。ArrayList實例都有一個屬性:capacity. capacity至少和size一樣大,它是自動增長的。它表示ArrayList可以存放的元素數目。
	private static final int DEFAULT_CAPACITY = 10; //默認capacity. 
	private static final Object[] EMPTY_ELEMENTDATA = {};//capacity 就是這個 array buffer的大小
	private transient Object[] elementData; //這就是arraylist最主要的元素:數組。
	public void ensureCapacity(int minCapacity) ;//這個方法以及之後的一系列方法都是用來操作capacity 的,它們可以讓capacity 增長。
	private void grow(int minCapacity) //這個方法展示了每次擴容擴多少,基本上相當於:newCapacity = oldCapacity + (oldCapacity >> 1);
	public int indexOf(Object o) //順序查找對象。線性時間
	public E get(int index) //索引獲取對象。常量時間
	public E set(int index, E element)//線性時間
	public boolean add(E e) //相當於線性時間
	public void add(int index, E element) //插入,線性時間
	public E remove(int index) //刪除,線性時間

LinkedList的源代碼:
	//它相當於一個雙向鏈表,它實現了List, Deque,它可以當做stack、queue、double-queue來用。
	transient Node<E> first; //頭結點
	transient Node<E> last;//最後一個結點
	private void linkFirst(E e) //將e連接至list頭部,成爲頭結點
	void linkLast(E e) //將e連接至list尾部,成爲尾結點
	void linkBefore(E e, Node<E> succ) //將e連接至succ之前
	private E unlinkFirst(Node<E> f) //assert f爲頭結點,將f解開連接。f的下一個結點成爲頭結點。
	private E unlinkLast(Node<E> l) //assert l爲尾結點,將l解開連接。
	private E unlink(Node<E> x) //將x解開連接
	public E getFirst() //獲取頭結點
	public E getLast() //獲取尾結點
	public E removeFirst() //同unlinkFirst,多了一個f是否爲空的判斷,可能拋出異常
	public E removeLast() //
	public void addFirst(E e) {linkFirst(e);}
	public void addLast(E e) {linkLast(e);}
	public boolean contains(Object o) //
	public boolean add(E e) //連接到尾部 常量時間
	public boolean remove(Object o) //線性時間
	public E set(int index, E element) //常量時間
	public void add(int index, E element) //常量時間
	public E remove(int index) //常量時間
	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;
    }
}



通常來說:在添加和刪除元素時具有比ArrayList更好的性能。但在get與set方面弱於ArrayList。

下一篇:ArrayList 、LinkedList 單線程操作對比。















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章