Arraylist 與 linkedlist新增資料速度測驗
以下是測試程式碼
public class Main { public static void main(String[] argv) { Test test = new Test(); List<Integer> list = new LinkedList<>(); long startTime = System.currentTimeMillis(); System.out.println("linkeLIst" + Calendar.getInstance().getTime()); test.listTest(list); System.out.println("linkeLIst" + Calendar.getInstance().getTime()); long endTime = System.currentTimeMillis(); System.out.println("linkedList " + String.valueOf(endTime - startTime)); List<Integer> list1 = new ArrayList<>(); long startTime1 = System.currentTimeMillis(); System.out.println("ArrayList" + Calendar.getInstance().getTime()); test.listTest(list1); System.out.println("ArrayList" + Calendar.getInstance().getTime()); long endTime1 = System.currentTimeMillis(); System.out.println("ArrayList " + String.valueOf(endTime1 - startTime1)); } }
public class Test
{
public void listTest(List<Integer> list)
{
Random random = new Random();
for (int i = 1; i < 150000; i++)
{
list.add(0,i);
}
}
}
測試arraylit時會註釋掉linkedlist的程式碼,反之亦然。
測試結果發現,入門教材上說的arrayList增刪速度比linkedList速度快是不完全正確的。插入的位置越是靠前linkedList的優勢就越明顯。速度是arrayList 10倍左右(這裡的測試資料是15000)。並且資料量越大,插入資料的位置越靠前,差距越明顯,arraylist比linkedList慢這個結論越正確。如果插入的位置是在末尾,則arraylist要比linkedList快數倍,這說明插入的位置很重要,如果只是末尾插入,則使用arraylist是最好的選擇
測試還發現,如果資料量小於10000。那麼arraylist的新增操作比linkedList還要快。無論是在什麼位置都是如此。這說明資料量不大的情況下arrayList的速度要優於linkedList。
以下是對arrayList和linkedList原始碼的個人理解
public void add(int index, E element) { checkPositionIndex(index); if (index == size) linkLast(element); else linkBefore(element, node(index)); }
上面這樣一段是linkedList的在指定的位置插入資料的原始碼。首先檢查索引位置,找到要插入資料的位置的指標。然後判斷是在末尾插入還是在其他位置插入。這樣一來,每次做新增操作都是需要搜尋指標位置。再進行插入操作,當資料量小的時候也是如此,這也是資料量小時,速度比arraylist還要慢的原因
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
以上這段是arraylist的原始碼。rangeCheckForAdd(index)先檢查插入的範圍。ensureCapacityInternal再確定是否超出陣列的長度。然後執行陣列拷貝的語句。如果超出現有陣列大小,則申請開闢新的記憶體空間(此處是時間開銷最大的部分)。然後再拷貝陣列,最後在新陣列指定的位置做賦值操作,並且陣列大小+1。
結論:資料量小,沒有超過arraylist陣列的上限,並且重新申請的記憶體空間不大,則速度上arraylist要比linkedList要快。如果資料量大,需要申請的記憶體空間越大,速度上arraylist就要比linkedList越慢。