java集合架構05——ArrayList和LinkedList的區別

來源:互聯網
上載者:User

本文為博主原創文章,轉載請註明出處:http://blog.csdn.net/eson_15/article/details/51145788


前面已經學習完了List部分的源碼,主要是ArrayList和LinkedList兩部分內容,這一節主要總結下List部分的內容。 List概括

        先來回顧一下List在Collection中的的架構圖:


    從圖中我們可以看出:

        1. List是一個介面,它繼承與Collection介面,代表有序的隊列。

        2. AbstractList是一個抽象類別,它繼承與AbstractCollection。AbstractList實現了List介面中除了size()、get(int location)之外的方法。

        3. AbstractSequentialList是一個抽象類別,它繼承與AbstrctList。AbstractSequentialList實現了“鏈表中,根據index索引值操作鏈結表的全部方法”。

        4. ArrayList、LinkedList、Vector和Stack是List的四個實作類別,其中Vector是基於JDK1.0,雖然實現了同步,但是效率低,已經不用了,Stack繼承與Vector,所以不再贅述。

        5. LinkedList是個雙向鏈表,它同樣可以被當作棧、隊列或雙端隊列來使用。

ArrayList和LinkedList區別
    我們知道,通常情況下,ArrayList和LinkedList的區別有以下幾點:

        1. ArrayList是實現了基於動態數組的資料結構,而LinkedList是基於鏈表的資料結構;

        2. 對於隨機訪問get和set,ArrayList要優於LinkedList,因為LinkedList要移動指標;

       3. 對於添加和刪除操作add和remove,一般大家都會說LinkedList要比ArrayList快,因為ArrayList要移動資料。但是實際情況並非這樣,對於添加或刪除,LinkedList和ArrayList並不能明確說明誰快誰慢,下面會詳細分析。

        我們結合之前分析的源碼,來看看為什麼是這樣的:

        ArrayList中的隨機訪問、添加和刪除部分源碼如下:

//擷取index位置的元素值public E get(int index) {    rangeCheck(index); //首先判斷index的範圍是否合法    return elementData(index);}//將index位置的值設為element,並返回原來的值public E set(int index, E element) {    rangeCheck(index);    E oldValue = elementData(index);    elementData[index] = element;    return oldValue;}//將element添加到ArrayList的指定位置public void add(int index, E element) {    rangeCheckForAdd(index);    ensureCapacityInternal(size + 1);  // Increments modCount!!    //將index以及index之後的資料複製到index+1的位置往後,即從index開始向後挪了一位    System.arraycopy(elementData, index, elementData, index + 1,                     size - index);     elementData[index] = element; //然後在index處插入element    size++;}//刪除ArrayList指定位置的元素public E remove(int index) {    rangeCheck(index);    modCount++;    E oldValue = elementData(index);    int numMoved = size - index - 1;    if (numMoved > 0)        //向左挪一位,index位置原來的資料已經被覆蓋了        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    //多出來的最後一位刪掉    elementData[--size] = null; // clear to let GC do its work    return oldValue;}
    LinkedList中的隨機訪問、添加和刪除部分源碼如下:

//獲得第index個節點的值public E get(int index) {checkElementIndex(index);return node(index).item;}//設定第index元素的值public E set(int index, E element) {checkElementIndex(index);Node<E> x = node(index);E oldVal = x.item;x.item = element;return oldVal;}//在index個節點之前添加新的節點public void add(int index, E element) {checkPositionIndex(index);if (index == size)linkLast(element);elselinkBefore(element, node(index));}//刪除第index個節點public E remove(int index) {checkElementIndex(index);return unlink(node(index));}//定位index處的節點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;} else { //index>=size/2時,從尾開始找Node<E> x = last;for (int i = size - 1; i > index; i--)x = x.prev;return x;}}
        從源碼可以看出,ArrayList想要get(int index)元素時,直接返回index位置上的元素,而LinkedList需要通過for迴圈進行尋找,雖然LinkedList已經在尋找方法上做了最佳化,比如index < size / 2,則從左邊開始尋找,反之從右邊開始尋找,但是還是比ArrayList要慢。這點是毋庸置疑的。
        ArrayList想要在指定位置插入或刪除元素時,主要耗時的是System.arraycopy動作,會移動index後面所有的元素;LinkedList主耗時的是要先通過for迴圈找到index,然後直接插入或刪除。這就導致了兩者並非一定誰快誰慢,下面通過一個測試程式來測試一下兩者插入的速度:

import java.util.ArrayList;  import java.util.Collections;  import java.util.LinkedList;  import java.util.List;  /* * @description 測試ArrayList和LinkedList插入的效率 * @eson_15      */public class ArrayOrLinked {      static List<Integer> array=new ArrayList<Integer>();      static List<Integer> linked=new LinkedList<Integer>();        public static void main(String[] args) {        //首先分別給兩者插入10000條資料        for(int i=0;i<10000;i++){              array.add(i);              linked.add(i);          }          //獲得兩者隨機訪問的時間        System.out.println("array time:"+getTime(array));          System.out.println("linked time:"+getTime(linked));          //獲得兩者插入資料的時間        System.out.println("array insert time:"+insertTime(array));          System.out.println("linked insert time:"+insertTime(linked));        }      public static long getTime(List<Integer> list){          long time=System.currentTimeMillis();          for(int i = 0; i < 10000; i++){              int index = Collections.binarySearch(list, list.get(i));              if(index != i){                  System.out.println("ERROR!");              }          }          return System.currentTimeMillis()-time;      }          //插入資料    public static long insertTime(List<Integer> list){     /*     * 插入的資料量和插入的位置是決定兩者效能的主要方面,     * 我們可以通過修改這兩個資料,來測試兩者的效能     */    long num = 10000; //表示要插入的資料量    int index = 1000; //表示從哪個位置插入        long time=System.currentTimeMillis();          for(int i = 1; i < num; i++){              list.add(index, i);             }          return System.currentTimeMillis()-time;                }    }  
        主要有兩個因素決定他們的效率,插入的資料量和插入的位置。我們可以在程式裡改變這兩個因素來測試它們的效率。

        當資料量較小時,測試程式中,大約小於30的時候,兩者效率差不多,沒有顯著區別;當資料量較大時,大約在容量的1/10處開始,LinkedList的效率就開始沒有ArrayList效率高了,特別到一半以及後半的位置插入時,LinkedList效率明顯要低於ArrayList,而且資料量越大,越明顯。比如我測試了一種情況,在index=1000的位置(容量的1/10)插入10000條資料和在index=5000的位置以及在index=9000的位置插入10000條資料的已耗用時間如下:

在index=1000出插入結果:array time:4linked time:240array insert time:20linked insert time:18在index=5000處插入結果:array time:4linked time:229array insert time:13linked insert time:90在index=9000處插入結果:array time:4linked time:237array insert time:7linked insert time:92
        從運行結果看,LinkedList的效率是越來越差。

        所以當插入的資料量很小時,兩者區別不太大,當插入的資料量大時,大約在容量的1/10之前,LinkedList會優於ArrayList,在其後就劣與ArrayList,且越靠近後面越差。所以個人覺得,一般首選用ArrayList,由於LinkedList可以實現棧、隊列以及雙端隊列等資料結構,所以當特定需要時候,使用LinkedList,當然咯,資料量小的時候,兩者差不多,視具體情況去選擇使用;當資料量大的時候,如果只需要在靠前的部分插入或刪除資料,那也可以選用LinkedList,反之選擇ArrayList反而效率更高。

        關於ArrayList和LinkedList的比較,就討論這麼多吧,如果有錯誤之處,請留言指正~

_____________________________________________________________________________________________________________________________________________________

-----樂於分享,共同進步。
-----更多文章請看:http://blog.csdn.net/eson_15

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.