ArrayList和LinkedList的add(E)性能祕密

二者末尾添加數據的性能如何?數組

我將經過程序和源碼來解析。數據結構

程序解析性能

這裏我將比較二者添加數據所消耗的時間。this

ArrayList<String> arr2 = new ArrayList<String>();
   LinkedList<String> link2 = new LinkedList<String>();
    long start =System.currentTimeMillis();
    for (int i = 0; i < asize; i++) {
        arr2.add("木子道_arrayList_"+i);
    }
    System.out.print("ArrayList exec add method " + asize + "|||");
    System.out.println(System.currentTimeMillis()- start +"/ms");
    start =System.currentTimeMillis();
    for (int i = 0; i < asize; i++) {
        link2.add("木子道_linkedList_"+i);
    }
    System.out.print("LinkedList exec add method " + asize + "|||");
    System.out.println( System.currentTimeMillis() - start + "/ms");

第一種結果:10萬數據的插入ArrayList平均耗時170毫秒,LinkedList平均耗時70毫秒 ArrayList exec add method 100000,耗時 170/ms LinkedList exec add method 100000,耗時 74/mscode

第二種結果:1萬數據的插入ArrayList平均耗時90毫秒,LinkedList平均耗時50毫秒 ArrayList exec add method 10000,耗時 94/ms LinkedList exec add method 10000,耗時 51/ms對象

第三種結果:5千數據的插入ArrayList平均耗時50毫秒,LinkedList平均耗時40毫秒 ArrayList exec add method 5000,耗時 51/ms LinkedList exec add method 5000,耗時 41/ms排序

第四種結果:1千數據的插入ArrayList平均耗時10毫秒,LinkedList平均耗時10毫秒 ArrayList exec add method 1000,耗時 9/ms LinkedList exec add method 1000,耗時 12/ms索引

以上的結果不是固定的,消耗的時間也不能決定因素,只作參考。內存

源碼解析 JDK1.7ci

//*********ArrayList******
//添加數據
public boolean add(E e) {
  //數據增長,容量不夠就擴容
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
//
private void ensureCapacityInternal(int minCapacity) {
    modCount++;
    // overflow-conscious code 默認在10一下不須要擴容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}
//擴容
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
   //按1.5倍擴容
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
   //擴容成功,容量固然也要改變啦。
    elementData = Arrays.copyOf(elementData, newCapacity);
}
//******LinkedList*******
//添加數據  
public boolean add(E e) {
      linkLast(e);
    return true;
}
//連接e做爲最後一個元素。
void linkLast(E e) {
    final Node<E> l = last;
  //相當重要。。。new一個節點對象
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

經過源碼發現ArrayList添加元素偶爾須要擴容。LinkedList每次都new一個對象,開銷是固定。 經過程序發現ArrayList隨着數據量大,性能遠遠比LinkedList差。

ArrayList使用數組存儲,實際上是一個內存連續塊,插入元素涉及數組元素移動等內存操做。 LinkedList使用雙向鏈表,將內存碎片經過引用關聯起來,造成一個能夠按序號索引的線性結構,這比數組連續方式相比,內存的利用率更高。插入數據只需記錄本先後節點便可。

總結

ArrayList:隨機訪問快,插入和刪除慢,基於數組的數據結構。

LinkedList:隨機訪問慢,插入和刪除快,基於雙向鏈表的數據結構。

ArrayList就是根據索引查。插入數組會複製成新數組,刪除會移動數組,重排序。

LinkedList只能從頭開始找,訪問會慢,插入和刪除不須要重排序因此快。

ArrayList擴容的時候會出現的結尾預留必定的容量空間的浪費。

LinkedList的每個元素容量空間是相等。

個人結論是:末尾添加數據量小的時候。ArrayList性能好,而數據量大則是LinkedList性能好。 歡迎指正。。。

▼長按如下二維碼便可關注▼

image

2018年請與我一塊兒打怪升級

相關文章
相關標籤/搜索