Java中ArrayList和LinkedList區別

來源:互聯網
上載者:User

一般大家都知道ArrayList和LinkedList的大致區別:
     1.ArrayList是實現了基於動態數組的資料結構,LinkedList基於鏈表的資料結構。
     2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指標。
     3.對於新增和刪除操作add和remove,LinedList比較佔優勢,因為ArrayList要移動資料。

ArrayList和LinkedList是兩個集合類,用於儲存一系列的對象引用(references)。例如我們可以用ArrayList來儲存一系列的String或者Integer。那麼ArrayList和LinkedList在效能上有什麼差別呢?什麼時候應該用ArrayList什麼時候又該用LinkedList呢?

一.時間複雜度
首先一點關鍵的是,ArrayList的內部實現是基於基礎的對象數組的,因此,它使用get方法訪問列表中的任意一個元素時(random access),它的速度要比LinkedList快。LinkedList中的get方法是按照順序從列表的一端開始檢查,直到另外一端。對LinkedList而言,訪問列表中的某個指定元素沒有更快的方法了。
假設我們有一個很大的列表,它裡面的元素已經排好序了,這個列表可能是ArrayList類型的也可能是LinkedList類型的,現在我們對這個列表來進行二分尋找(binary search),比較列表是ArrayList和LinkedList時的查詢速度,看下面的程式:

Java代碼 {
dp.sh.Toolbar.CopyToClipboard(this);return false;
}" href="http://writeblog.csdn.net/#">
  1. package com.mangocity.test;    
  2. import java.util.LinkedList;    
  3. import java.util.List;    
  4. import java.util.Random;    
  5. import java.util.ArrayList;    
  6. import java.util.Arrays;    
  7. import java.util.Collections;    
  8. public class TestList ...{    
  9.      public static final int N=50000;    
  10.   
  11.      public static List values;    
  12.   
  13.      static...{    
  14.          Integer vals[]=new Integer[N];    
  15.   
  16.          Random r=new Random();    
  17.   
  18.          for(int i=0,currval=0;i<N;i++)...{    
  19.              vals=new Integer(currval);    
  20.              currval+=r.nextInt(100)+1;    
  21.          }    
  22.   
  23.          values=Arrays.asList(vals);    
  24.      }    
  25.   
  26.      static long timeList(List lst)...{    
  27.          long start=System.currentTimeMillis();    
  28.          for(int i=0;i<N;i++)...{    
  29.              int index=Collections.binarySearch(lst, values.get(i));    
  30.              if(index!=i)    
  31.                  System.out.println("***錯誤***");    
  32.          }    
  33.          return System.currentTimeMillis()-start;    
  34.      }    
  35.      public static void main(String args[])...{    
  36.          System.out.println("ArrayList消耗時間:"+timeList(new ArrayList(values)));    
  37.          System.out.println("LinkedList消耗時間:"+timeList(new LinkedList(values)));    
  38.      }    
  39. }   
package com.mangocity.test; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; public class TestList ...{      public static final int N=50000;      public static List values;      static...{          Integer vals[]=new Integer[N];          Random r=new Random();          for(int i=0,currval=0;i<N;i++)...{              vals=new Integer(currval);              currval+=r.nextInt(100)+1;          }          values=Arrays.asList(vals);      }      static long timeList(List lst)...{          long start=System.currentTimeMillis();          for(int i=0;i<N;i++)...{              int index=Collections.binarySearch(lst, values.get(i));              if(index!=i)                  System.out.println("***錯誤***");          }          return System.currentTimeMillis()-start;      }      public static void main(String args[])...{          System.out.println("ArrayList消耗時間:"+timeList(new ArrayList(values)));          System.out.println("LinkedList消耗時間:"+timeList(new LinkedList(values)));      } } 

 
我得到的輸出是:ArrayList消耗時間:15
                 LinkedList消耗時間:2596
這個結果不是固定的,但是基本上ArrayList的時間要明顯小於LinkedList的時間。因此在這種情況下不宜用LinkedList。二分尋找法使用的隨機訪問(random access)策略,而LinkedList是不支援快速的隨機訪問的。對一個LinkedList做隨機訪問所消耗的時間與這個list的大小是成比例的。而相應的,在ArrayList中進行隨機訪問所消耗的時間是固定的。
這是否表明ArrayList總是比LinkedList效能要好呢?這並不一定,在某些情況下LinkedList的表現要優於ArrayList,有些演算法在LinkedList中實現時效率更高。比方說,利用Collections.reverse方法對列表進行反轉時,其效能就要好些。
看這樣一個例子,加入我們有一個列表,要對其進行大量的插入和刪除操作,在這種情況下LinkedList就是一個較好的選擇。請看如下一個極端的例子,我們重複的在一個列表的開端插入一個元素:

Java代碼 {
dp.sh.Toolbar.CopyToClipboard(this);return false;
}" href="http://writeblog.csdn.net/#">
  1. package com.mangocity.test;    
  2.   
  3. import java.util.*;    
  4. public class ListDemo {    
  5.      static final int N=50000;    
  6.      static long timeList(List list){    
  7.      long start=System.currentTimeMillis();    
  8.      Object o = new Object();    
  9.      for(int i=0;i<N;i++)    
  10.          list.add(0, o);    
  11.      return System.currentTimeMillis()-start;    
  12.      }    
  13.      public static void main(String[] args) {    
  14.          System.out.println("ArrayList耗時:"+timeList(new ArrayList()));    
  15.          System.out.println("LinkedList耗時:"+timeList(new LinkedList()));    
  16.      }    
  17. }   
package com.mangocity.test; import java.util.*; public class ListDemo {      static final int N=50000;      static long timeList(List list){      long start=System.currentTimeMillis();      Object o = new Object();      for(int i=0;i<N;i++)          list.add(0, o);      return System.currentTimeMillis()-start;      }      public static void main(String[] args) {          System.out.println("ArrayList耗時:"+timeList(new ArrayList()));          System.out.println("LinkedList耗時:"+timeList(new LinkedList()));      } } 

 這時我的輸出結果是:ArrayList耗時:2463

 

                           LinkedList耗時:15
這和前面一個例子的結果截然相反,當一個元素被加到ArrayList的最開端時,所有已經存在的元素都會後移,這就意味著資料移動和複製上的開銷。相反的,將一個元素加到LinkedList的最開端只是簡單的未這個元素分配一個記錄,然後調整兩個串連。在LinkedList的開端增加一個元素的開銷是固定的,而在ArrayList的開端增加一個元素的開銷是與ArrayList的大小成比例的。

二.空間複雜度
在LinkedList中有一個私人的內部類,定義如下:

Java代碼 {
dp.sh.Toolbar.CopyToClipboard(this);return false;
}" href="http://writeblog.csdn.net/#">
  1. private static class Entry {    
  2.          Object element;    
  3.          Entry next;    
  4.          Entry previous;    
  5.      }   
private static class Entry {          Object element;          Entry next;          Entry previous;      } 

 
每個Entry對象reference列表中的一個元素,同時還有在LinkedList中它的上一個元素和下一個元素。一個有1000個元素的LinkedList對象將有1000個連結在一起的Entry對象,每個對象都對應於列表中的一個元素。這樣的話,在一個LinkedList結構中將有一個很大的空間開銷,因為它要儲存這1000個Entity對象的相關資訊。
ArrayList使用一個內建的數組來儲存元素,這個數組的起始容量是10.當數組需要增長時,新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會增長50%。這就意味著,如果你有一個包含大量元素的ArrayList對象,那麼最終將有很大的空間會被浪費掉,這個浪費是由ArrayList的工作方式本身造成的。如果沒有足夠的空間來存放新的元素,數組將不得不被重新進行分配以便能夠增加新的元素。對數組進行重新分配,將會導致效能急劇下降。如果我們知道一個ArrayList將會有多少個元素,我們可以通過構造方法來指定容量。我們還可以通過trimToSize方法在ArrayList分配完畢之後去掉浪費掉的空間。

三.總結
ArrayList和LinkedList在效能上各有優缺點,都有各自所適用的地方,總的說來可以描述如下:
1.對ArrayList和LinkedList而言,在列表末尾增加一個元素所花的開銷都是固定的。對ArrayList而言,主要是在內部數組中增加一項,指向所添加的元素,偶爾可能會導致對數組重新進行分配;而對LinkedList而言,這個開銷是統一的,分配一個內部Entry對象。

2.在ArrayList的中間插入或刪除一個元素意味著這個列表中剩餘的元素都會被移動;而在LinkedList的中間插入或刪除一個元素的開銷是固定的。

3.LinkedList不支援高效的隨機元素訪問。

4.ArrayList的空間浪費主要體現在在list列表的結尾預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗相當的空間

可以這樣說:當操作是在一列資料的後面添加資料而不是在前面或中間,並且需要隨機地訪問其中的元素時,使用ArrayList會提供比較好的效能;當你的操作是在一列資料的前面或中間添加或刪除資料,並且按照順序訪問其中的元素時,就應該使用LinkedList了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.