Java容器——ArrayList VS LinkedList(Java8) 性能比較

ArrayList和LinkedList都繼承自List, 內在實現機制有所不同,關於區別方面已經有很多優秀的文章進行了介紹。本文從實踐角度出發,對比兩種List在不同操作中的性能,便於讀者在特定場景中參考選型。由於電腦配置,JDK版本,IDE等會導致測試結果又出入甚至有結論不太一致的結果,本文的試驗結果僅具備一定的參考價值。

    一 插入數據

以同樣的方式向兩種List中插入數據,首先插入簡單類型數據,這裏插入簡單字符串。表中數據以毫秒爲單位,不到1毫秒的近似爲1毫秒。

     /**
     * add element for List
     * @param sourceArray  source element array
     * @param list  list to add element
     */
    public void setEleForList(Object[] sourceArray, List list){
        int len = sourceArray.length;
        for (int i = 0; i < len; i++){
            list.add(sourceArray[i]);
        }
    }
表1 兩種List插入性能對比
操作條數 ArrayList         LinkedList
1000 6     1
10000 13     1
100000 10 19
1000000 24 45
1000000 347     939

表中的數據時間單位都是毫秒。明顯可見,在數量較少的情況下,LinkedList有絕對的速度優勢,超過100000條以上,ArrayList就佔據了明顯的優勢。

二 讀取List數據

查找數據是容器的一項重要操作,通常而言取數據要比存入和修改來得更頻繁。在遍歷列表方面,二者對比如何呢。這裏採用兩種讀取的方式,一種是順序讀取,一種是隨機選擇。

     /**
     * iterate through list
     *
     * @param list list to iterate through
     */
    public void getAllEleFromList(List list){
        int size = list.size();
        for (int i = 0; i < size; i++){
            Object object = list.get(i);
        }
    }
表2 兩種List順序遍歷性能對比
操作條數 ArrayList         LinkedList
1000 1 2
10000 1 34
100000 2 5435
  /**
     * get random elements form list
     *
     * @param list list to get from
     * @param num number of elements to get
     */
    public void getRandomEleFromList(List list,int num){
        int size = list.size();
        Random random = new Random();
        for (int i = 0; i < num; i++){
            Object object = list.get(random.nextInt(size - 1));
        }
    }
表3 兩種List隨機遍歷性能對比
操作條數 ArrayList         LinkedList
1000 1 1
10000 3 40
100000 6

6420

List的順序遍歷有多重方式,二者統一採取了按下標遞增遍歷的方式進行。隨機讀取的次數和列表的長度相同,在測試時間上需要加上產生隨機數的時間。鑑於二者在十萬條數據上差別已經巨大,不再繼續測試。
   

三 刪除List數據

對List的刪除操作是容易產生異常的地方,日常操作時要格外小心。這裏隨機對列表已有元素進行刪除。刪除的數量爲列表長度的十分之一。

 /**
     * remove random number elements form list
     *
     * @param list list to remove
     * @param num  number to remove
     */
    public void removeEleFromList(List list, int num){
        int size = list.size();
        Random random = new Random();
        for (int i = 0; i < num; i++){
            Object object = list.remove(random.nextInt(size - 1 - i));
        }
    }
表4 兩種List刪除性能對比
操作條數 ArrayList         LinkedList
1000 1 1
10000 2 8
100000 45 893
1000000 6261 73234

可見,和插入、查詢相比,List的刪除是最耗時間的操作也最容易出問題。

四 清除List數據

有建立,就有銷燬,如果銷燬List採用上面逐個刪除的方式,那這個時間代價是不能接受的。系統採用的清除List的方式要簡便快速許多,這裏就不貼系統代碼了,直接看時間對比。

表5 兩種List銷燬對比
操作條數 ArrayList         LinkedList
1000 1 1
10000 1 1
100000 1 3
1000000 3 6
1000000 11 42

總結

通過測試數據可得,在大部分場景下,ArrayList是優於LinkedList的,只有在少量數據插入時,LinkedList有一定優勢。

本文對List的重要操作性能進行了對比,List接口還有很多實現方法,感興趣的話可以自己親手實踐。

理論要聯繫實際,從實踐中總結理論。造成測試結果的原因是多方面的,不僅僅依賴接口的實現,與參數類型,操作系統,虛擬機都可能有關,後面我們會從源碼的角度解讀測試結果。

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