1. 程式人生 > >增加和刪除資料時,為什麼LinkedList通常比ArrayList快?

增加和刪除資料時,為什麼LinkedList通常比ArrayList快?

實驗 

首先我們做一個實驗:將10萬條String型別的資料分別新增到一個LinkedList和一個ArrayList中,且每次都是在第0位(即首位)插入資料,程式碼如下

結果是LinkedList比ArrayList要快: ArrayList平均用了500毫秒,而LinkedList平均只用了15毫秒;進行多次實驗你就會發現,新增的資料量越大,LinkedList的速度優勢越明顯,這是為什麼呢?

import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class ListAddTest {

    List<String> arrList = new ArrayList<String>();
    List<String> lnkList = new LinkedList<String>();

    void add(List<String> list) {

        long startTime = System.currentTimeMillis();
        System.out.println("開始的時間:" + startTime);
        for (int i = 0; i < 100000; i++) {
            list.add(0, String.valueOf(i));
        }
        long endTime = System.currentTimeMillis();
        System.out.println("結束的時間:" + endTime);
        System.out.println("總耗時:" + (endTime - startTime));

    }

    @Test
    public void addTimeTest() {

        add(arrList);
        // 開始的時間:1487783199226
        // 結束的時間:1487783199741
        // 總耗時:515

        add(lnkList);
        // 開始的時間:1487783199741
        // 結束的時間:1487783199756
        // 總耗時:15

    }

}

分析 

首先,閱讀JDK的文件,我們從中可以知道,ArrayList實際上是一個可變長的陣列,LinkedList則是由相互引用的節點組成的雙向連結串列

緊接著我們就要知道,在增加資料時LinkedList和ArrayList分別在底層發生了什麼?於是略讀JDK原始碼我們就可以得出:

● 既然LinkedList是一個由相互引用的節點組成的雙向連結串列,那麼當把資料插入至該連結串列某個位置時,該資料就會被組裝成一個新的節點,隨後只需改變連結串列中對應的兩個節點之間的引用關係,使它們指向新節點,即可完成插入(如下圖);同樣的道理,刪除資料時,只需刪除對應節點的引用即可


● 而ArrayList是一個可變長陣列,插入資料時,則需要先將原始陣列中的資料複製到一個新的陣列,隨後再將資料賦值到新陣列的指定位置(如下圖)

;刪除資料時,也是將原始陣列中要保留的資料複製到一個新的陣列


結論 

因此,在新增或刪除資料的時候,ArrayList經常需要複製資料到新的陣列,而LinkedList只需改變節點之間的引用關係,這就是LinkedList在新增和刪除資料的時候通常比ArrayList要快的原因