jdk源碼ArrayList學習體會分析二

ArrayList就是一個可調整大小的數組,即可動態的增減元素,改變數組大小。

以下是我閱讀ArrayList源碼的一點心得及總結:

首先,ArrayList定義:


可以看出ArrayList是支持泛型的ArrayList<E>,繼承AbstractList,實現LIst,RandomAccess, Cloneable, java.io.Serializable接口

其中LIst也是支持泛型的,定義了列表必須實現的方法。

RandomAccess是個標記接口,無內容。如果List子類實現了RandomAccess接口,那就表示它能夠快速隨機的訪問元素。

即:ArrayList實現RandomAccess接口,意義在於訪問列表時,可以選擇最佳方式快速的訪問。

Cloneable標識接口,無內容。實現Cloneable類,可以調用Object.clone()方法返回對象的淺拷貝。

實現java.io.Serializable接口即可啓用序列化功能。

ArrayList屬性,2個私有屬性


elementData是ArrayList存儲的元素,size是ArrayList的大小。

實現java.io.Serializable接口,將不需要序列化的屬性前加上transient關鍵字,序列化對象時,該屬性就不會被序列化到指定的目的地中。


ArrayList提供了3個構造方法以滿足不同需求:

先看前2個:


第一個構造方法是根據傳遞的initialCapacity來初始化數組的大小,如果傳遞的值小於0 ,就會拋出參數不合法提示。

第二個構造方法調用第一個構造方法傳入10來初始化數組,即數組大小爲10.

下面來看第三個構造方法,如下:


將傳遞的集合轉換成數組返回給elementData(返回的如果不是Object[],則調用Arrays.copyOf方法轉爲Object[])

Arrays.copyOf方法的具體實現:


首先是分配一個大小爲newLengthd的Object,再調用系統方法arraycopy將original拷貝到copy中,從位置0開始拷貝newLength個長度,拷貝到copy中也是從位置0開始賦值,最後返回copy.


ArrayList的其他方法:

ensureCapacity(int minCapacity)方法,確保數組的最小容量


傳遞參數爲minCapacity,用oldCapacity記下原來數組的大小,如果minCapacity的值大於原來數組大小,則需要增加容量來確保數組的容量夠用。

如何增加的 呢?

使用(oldCapacity * 3)/2 + 1賦值給新的容量newCapacity,那麼接下來就該判斷新容量newCapacity和傳遞的minCapacity的大小了。如果newCapacty小於minCapacity,則說明定義的新容量太小不能滿足要求,所以要把minCapacity賦值給新容量newCapacty作爲原來數組的大小;否則說明新容量newCapacty大於傳遞的參數,可以滿足要求,這樣就保證來了最終的newCapacity是大於或等於傳遞的minCapacity的,即copy返回的最終elementData數組不會出現越界問題。

最後調用Arrays.copyOf方法把newCapacity作爲數組的大小copy返回給elementData。


IndexOf()方法:


遍歷數組elementData,如果傳遞的O在數組中存在即和某個值相等,則返回所在索引即【0,size-1】,若不存在則返回-1.

注:若存在多個,則返回第一次出現的位置(滿足條件的lowest),是順序遍歷的。

與之相反的是lastIndexOf()方法:


遍歷數組返回最後一次和O相等的位置,所以倒序遍歷數組找第一次出現O的位置即可,並返回下標。


add(E e)在數組尾部添加元素


首先調用ensureCapacity(size+1)方法確保數組容量,上面已經解釋過,調用此方法傳遞size+1,則數組elementData容量至少是size+1,即至少容量增加了一個,所以再給elementData[size}=e不會越界,賦值後屬性size++自增1.

add(int index,E element),添加指定元素到指定位置:


首先判斷傳遞的指定位置index是否在合理範圍內【0,size】,若不滿足則拋出越界異常(如果等於size,則是在數組尾端添加元素element)

調用ensureCapaCity(size+1)保證數組容量至少增加1,之後調用System.arrayCopy()方法,將數組elementData從特定位置index開始拷貝size-index個長度(即index之後的元素)到elementData數組(拷貝的元素賦值從index+1開始),換句話說就是把從index位置(如是第5個元素)後的元素全部後移一位(放到第6位),依次類推共size-index個元素直至把elementData[size-1]最後一個元素放到新的elementData[size]中,此時size還是原來的size大小。

再把指定元素放到index(第5個位置)上,即elemnetData[index]=elment;最後size自增1.


刪除指定位置的元素remove(int index):


與添加指定元素到指定位置類似,RangeCheck(index)檢查index是否在合理的範圍內【0,size-1】

muMoved=(size-1)-index;意爲需要移動的元素個數,如果要刪除的是第一個位置0,則需要把size-1個元素即除去原本的第一個元素,其他所有後面的元素均要向前移動一位(這裏不是真的移動,是吧後面 的index+1位置元素拷貝到index位置上,形象的理解爲向前移動)。最後size--自減1,最後空出的位置賦值爲null.返回刪除的元素oldValue.

一點小小理解,暫時寫到這。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章