標籤:target 最大值 blank 修改 基礎 情況下 shu 出現 異常
轉載請註明http://www.cnblogs.com/majianming/p/8006452.html
有人問我,java ArrayList底層是怎麼實現的?我就回答數組,他再問我,那它是怎麼實現數組的添加的呢?我也不知道,就不敢回答了。
回來趕緊看了一下java實現,明確的是ArrayList底層的確是用數組實現的,但是怎麼實現數組的擴容的呢?
簡單來說,就是建立一個新的比原來大的數組,把原來所有的元素複製到新的數組,然後添加新的數組進去
先從無參建構函式開始,無參建構函式建立了一個容量為0的空數組(這裡要注意,在jdk1.8時採用的是建立空數組,在1.7還是建立了一個容量為10的數組,源碼見附錄1,2,這裡以1.8為例)
然後就可以開始調用add方法添加元素,這裡先以public boolean add(E e)方法為例
- 計算最小容量:判斷是不是第一次添加,準確來說是不是一個空數組。如果是一個空數組,那麼設定初始化大小(即最小容量)為10,如果不是,那麼在原來基礎上大小+1。
- 判斷是否需要擴容:判斷最小容量是不是大於數組長度(至少大1),如果是,進行第3步。為什麼有這個判斷?是最小容量是數組可以存放的元素個數,而數組長度是實際上存放的個數,那麼就會出現數組還沒放滿的情況,比如第二次添加時,數組容量為10(第一次初始化時設定為10),元素加上新增加的只有兩個,是不需要進行第3,4步的
- 擴容計算:
- 取得已有元素的個數,準備設定新的容量為原來元素個數的1.5倍
- 將1中的新容量和最小容量相對比,取大的(所以初始化時原來元素的1.5倍為0小於最小容量10,設定為10)
- 將2中計算結果與Integer.MAX_VALUE - 8對比(為啥是-8 ,doc上是說明了一些虛擬機器實現需要多存一些頭資訊,為了防止oom,其他沒有說明,在stackoverflow上說明了為了存下數組的最大大小2,147,483,648所以需要(見附錄3))還大,那就沒辦法了,只能設定為Integer.MAX_VALUE。也就是說正常情況下數組最大容量為下最大值減8,否則就是最大值。這個時候放不下那就只能拋異常了唄!
- 複製舊元素到新數組:上一步計算的只是一個值,沒有對原來的進行修改,也沒有建立新的數組。接下來使用Arrays.copyOf將原來數組的所有元素複製到新數組(以最小容量建立的),並返回
- 把添加的元素添加到新返回的數組最後,長度+1
附錄
- jdk 1.7 ArrayList
- jdk 1.8 ArrayList
- 為什麼-8
參考
Java中ArrayList源碼淺析
設定
jdk:1.8_102
轉載請註明http://www.cnblogs.com/majianming/p/8006452.html
jdk 1.8下 java ArrayList 添加元素解析