java ArrayList和LinkedList的區別


  通常情況下,ArrayList和LinkedList的區別有以下幾點:
         1. ArrayList是實現了基於動態數組的數據結構,而LinkedList是基於鏈表的數據結構
         2. 對於隨機訪問get和set,ArrayList要優於LinkedList,因為LinkedList要移動指針
        3. 對於添加和刪除操作add和remove,一般大家都會說LinkedList要比ArrayList快,因為ArrayList要移動數據

  實際情況並非這樣,對於添加或刪除,LinkedList和ArrayList並不能明確說明誰快誰慢,結合之前分析的源碼,來看看為什么是這樣的,ArrayList中的隨機訪問、添加和刪除部分源碼如下:

  

 

  

 

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

  

 

   

 

   

 

  從源碼可以看出,ArrayList想要get(int index)元素時,直接返回index位置上的元素,而LinkedList需要通過for循環進行查找,雖然LinkedList已經在查找方法上做了優化,比如index < size / 2,則從左邊開始查找,反之從右邊開始查找,但是還是比ArrayList要慢。這點是毋庸置疑的。
        ArrayList想要在指定位置插入或刪除元素時,主要耗時的是System.arraycopy動作,會移動index后面所有的元素;LinkedList主耗時的是要先通過for循環找到index,然后直接插入或刪除。這就導致了兩者並非一定誰快誰慢,下面通過一個測試程序來測試一下兩者插入的速度:

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:4
linked time:240
array insert time:20
linked insert time:18
 
在index=5000處插入結果:
array time:4
linked time:229
array insert time:13
linked insert time:90
 
在index=9000處插入結果:
array time:4
linked time:237
array insert time:7
linked insert time:92


  從運行結果看,LinkedList的效率是越來越差
       所以當插入的數據量很小時,兩者區別不太大,當插入的數據量大時,大約在容量的1/10之前,LinkedList會優於ArrayList,在其后就劣與ArrayList,且越靠近后面越差。所以個人覺得,一般首選用ArrayList,由於LinkedList可以實現棧、隊列以及雙端隊列等數據結構,所以當特定需要時候,使用LinkedList,當然咯,數據量小的時候,兩者差不多,視具體情況去選擇使用;當數據量大的時候,如果只需要在靠前的部分插入或刪除數據,那也可以選用LinkedList,反之選擇ArrayList反而效率更高。
  但是,這個實驗結果明顯不對,增加和刪除數據的時候,ArrayList都是在末尾添加數據,arraycopy的開銷是最低的,LinkedList添加數據總是在末尾,每次都要遍歷整個鏈表,ArrayList比LinkedList效率要高,而實際隨機添加和刪除,從大概率上來講,ArrayList性能還是低於LinkedList
  建議測試用例考慮三個因素:

     1)被測試的list的長度,可分為min, max兩種情況

     2)插入的list的長度,也可分為較小,較大兩種情況

     3)插入的位置,不妨考慮第二個位置,倒數第二個位置。 然后做組合出8種情況,測試的結果填寫表格,得出初步結論:大數據量插入linked比較快,小數據量arraylist比較快

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM