因為ArrayList底層是數組實現的,根據下標查詢不需要比較,查詢方式為,首地址+(元素長度*下標),基於這個位置讀取相應的字節數就可以了,所以非常快;
增刪會帶來元素的移動,增加數據會向后移動,刪除數據會向前移動,所以影響效率。
相反,在添加或刪除數據的時候,LinkedList只需改變節點之間的引用關系,這就是LinkedList在添加和刪除數據的時候通常比ArrayList要快的原因,
查詢時通過二分法查找。
插入
LinkedList:
通過add(int index, E element)向LinkedList插入元素時。先是在雙向鏈表中找到要插入節點的位置index;找到之后,再插入一個新節點。
雙向鏈表查找index位置的節點時,有一個加速動作:若index < 雙向鏈表長度的1/2,則從前向后查找; 否則,從后向前查找。
ArrayList:
ensureCapacity(size+1) 的作用是“確認ArrayList的容量,若容量不夠,則增加容量。”
真正耗時的操作是 System.arraycopy(elementData, index, elementData, index + 1, size - index);
Sun JDK包的java/lang/System.java中的arraycopy()聲明如下:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
arraycopy()是個JNI函數,它是在JVM中實現的。sunJDK中看不到源碼,不過可以在OpenJDK包中看到的源碼。網上有對arraycopy()的分析說明,請參考:System.arraycopy源碼分析
實際上,我們只需要了解: System.arraycopy(elementData, index, elementData, index + 1, size - index); 會移動index之后所有元素即可。這就意味着,ArrayList的add(int index, E element)函數,會引起index之后所有元素的改變!
刪除同插入原理
查詢
LinkedList:通過get(int index)獲取LinkedList第index個元素時。先是在雙向鏈表中找到要index位置的元素;找到之后再返回。
雙向鏈表查找index位置的節點時,有一個加速動作:若index < 雙向鏈表長度的1/2,則從前向后查找; 否則,從后向前查找。
ArrayList:通過get(int index)獲取ArrayList第index個元素時。直接返回數組中index位置的元素,而不需要像LinkedList一樣進行查找。