增加和刪除資料時,為什麼LinkedList通常比ArrayList快?
阿新 • • 發佈:2019-01-02
實驗
首先我們做一個實驗:將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要快的原因