JAVA ArrayList集合底層原始碼分析

安生_DL50發表於2022-03-08

ArrayList集合

一、ArrayList的注意事項

  1. ArrayList集合可以加入null,並且可以加入多個
  2. ArrayList是由陣列來實現的資料儲存的
  3. ArrayList基本等同於Vetor,但是ArrayList是執行緒不安全的(執行效率高),在多執行緒下不建議使用ArrayList

二、 ArrayList 的底層操作機制原始碼分析(重點,難點.)

1.JDK8.0

  1. ArrayList中存放了一個Object型別的陣列elementDate,什麼型別都能往裡面放
    • transient Object[] elementDate;
      • transient表示該屬性不會被序列化
  2. 當建立ArrayList物件時,如果使用的是無參構造器,則初始elementData容量為0,第1次新增,則擴容elementData為10,如需要再次擴容,則擴容elementData為1.5倍
  3. 如果使用的是指定大小的構造器,則初始elementData容量為指定大小,如果需要擴容,則直接擴容elementData為1.5倍。

注意:

  • mount 表示的該陣列的修改次數

注意:

  • >>1代表二進位制位向右移兩位,表示大小/2,這裡的int newCapacity = oldCapacity + (oldCapacity >> 1),代表擴容按舊陣列的1.5倍進行擴容(除第一次).
  • newCapacity - minCapacity < 0
    • 第一次擴容:newCapacity = 0minCapacity = 10,即當最小容量比新容量小的時候,把minCpacaity 賦給 newCapacity,只有第一次擴容會執行這個if
      • 如果newCapacity 比最大的大小還要大時
      • 執行hugeCapacity這個方法
    • 利用copyOf,把原陣列的內容拷貝到新陣列裡面去,並讓elementData指向該方法返回回來的地址,這樣可以在保留原來陣列中元素的同時,並增加新的空間,新空間預設為null;

若是使用指定大小的構造器

  • 第一次擴容就按照elemenData的1.5倍擴容
    • 整個執行流程還是和前面講的一樣

2.JDK11.0

使用ArrayList無參構造器,會建立一個只讀的靜態的,型別為Object的空陣列

儲存資料底層實現原理:

  1. 呼叫add方法,引數:e為你要儲存的資料(大概).
  2. modCount:為對該集合的操作次數,預設為0
  3. 呼叫 add 方法(過載後的add方法)

  • 當前元素個數 == 當前陣列長度,就會進行擴容
    • 之後讓elementData[s] = e,s為當前元素個數,且讓size = s +1
  1. 如果要進行擴容

  • 返回一個擴容後的陣列,利用copyOf方法,把原來的陣列元素,拷貝到新陣列中,且新陣列的長度為原來陣列+1;
  • 然後在執行下面的賦值操作,同上

newCapacity方法

  • 呼叫newCapacity,確定要擴大的空間
  • oldCapacity 為當前陣列的長度
  • newCapacity 為擴容後新陣列的長度:為舊陣列長度的1.5倍

如果新陣列的長度,比需要的(最小)容量小,則執行下面的程式碼

  • DEFAULT_CAPACITY為int 型別 ,值為10,如果elementaData 為空陣列(DEFAULTCAPACTY_EMPTY_ELEMENTDATA),那麼就用把mincapacity和DEFAULT_CAPACITY傳進去進行比較,返回最大值,這個最大值就是要新陣列的容量
    • 如果minCapacity<0 則丟擲異常
    • 並返回mincapacity

如果新陣列的長度,大於需要的(最小)容量,則執行下面的程式碼

  • 三元表示式,這裡比較簡單不做闡述

相關文章