Java集合系列-ArrayList源碼分析(1)

? ? ? ?在我們的日常開發工作當中,集合用到的次數非常多,常用的List集合有ArrayList, ? ? ? ?LindedList等等,今天我們從源碼的角度來分析一下ArrayList的工作原理,搞清楚它 ? ? ? ? 的內部是如何存儲數據,如何工作的。

1:我們要了解它的原理,首先從如何使用來看,通過new產生一個實例;如下:

? ? ? List list = new ArrayList(); 我們點擊進去,看它的構造里面是什么?

咦?array是什么鬼?點擊一下

原來

原來它是一個Object數組,就是說ArrayList的數據很有可能是保存在這個array的數組當中的,我們再次回到他的構造方法,array = EmptyArray.OBJECT;

EmptyArray.OBJECT; ??? 這是什么捏?讓我們來查看下這個EmptyArray類。

這下就清晰了,它其實是引用了一個大小為0的Object 數組對象。

我們再來看一下它的其他構造:

我們

我們看到當capacity == 0 ?的時候和上一個構造邏輯是一樣的,如果大于0的話就直接new了一個capacity大小的Object 數組對象。

collection參數是一個集合,首先轉換集合為Object[];

判斷如果不等于Object[].class;重新new一個大小相等的Object數組, 然后把a數組里的數據全部copy到newArray數組里面;再把a的引用指給newArray。

如果等于的話直接濾過上面的過程;

然后把array的引用指向a,并且賦值size字段。

至此所有構造方法大家都了解了;下一步我們來看看它的add方法。

2:我們先來看看它的所有add方法

可以看出總共有4個add方法,讓我們一個一個來跟蹤;

? ? 2.1:第一個add(Object object)

首先把array賦值給a數組;把size(表示當前添加了多少數據的大小)變量賦值給s。
然后判斷如果s == a.length,如果當前已添數據的大小已經和a數組的大小相同了,已經無法再添加數據了,這個時候需要擴充數組大小,來容納新添加的數據;

首先new一個新的數組,重要是看數組的大小。大小等于它當前的大小s加上后面的邏輯判斷,邏輯判斷:這里有一個最小容量MIN_CAPACITY_INCREMENT=12,如果當前的大小小于最小容量的一半,那就用當前的大小s+最小容量,組合新的數組大小;反之如果大于最小容量的一半;那就用當前的大小s+(s>>1 ps : 就是s/2);然后copy原來數組中的數據到新的數組當中,再把新數組newArray賦值給a賦值給array;

然后設置a[s] = object;把新數據添加到數組中,然后改變size大小。

2.2:第二個add(int index,E object),在第index個位置添加object數據;

挑重點看;

if(s < a.length) {

System.arraycopy(a,index,a,index +1,s - index);

}

上面的代碼意思:

如果當前添加數據的數量小于數組的總長度;就是說如果數組的總長度是10,但是我們當前只添加了5條數據;然后進行copy數據,其實就是數據的移動;

從a數組中的index位置開始copy,copy的長度為s-index,還是copy到a數組,從index+1的位置開始copy,通俗一點講就是:把index位置的數據以及后面的數據通通往后移一位;然后把新添加的數據添加到index的位置。

反之請看:

Object[] newArray =newObject[newCapacity(s)];

System.arraycopy(a,0,newArray,0,index);

System.arraycopy(a,index,newArray,index +1,s - index);

array= a = newArray;

重新new一個Object數組,數組的大小依據上一個add方法的邏輯判斷;然后把數組a當中的數據從0開始copy,copy的長度為index,copy到newArray當中;然后再把從index之后的數據copy到newArray當中去,從index+1的位置開始copy,剩下就是把要添加的數據object設置到index的位置。

用個圖來看下可能會清晰一點,好理解;


如果index=2,兩個copy方法就分別把1和2 copy到index的前面,然后把3,4,5 copy到index 的后面;

然后把要添加的Object賦值給index位置。

2.3:addAll(Collection collection) 添加一個集合到list

和上面2個邏輯差不多;把新集合的大小和當前list的大小加到一起判斷;

如果大于當前list的大小,就new一個新的數組,進行數據copy;

反之就是把新集合的數據copy到當前list當中,從最后位置開始copy。

2.4:addAll(int index,Collection collection) 從指定的index位置添加集合;

和2.2的邏輯差不多,就是移動的位置由1位變成了新集合的長度。

到此位置,list的add方法都已經分析完成了。

可以看出來ArrayList其實就是對數組的操作,在添加的過程中,不斷的改變數組的大小來適應數據量,所以我們以后使用ArrayList的時候如果已經得知要添加的數據量,最好使用可以設置數組大小的那個構造方法,這樣可以減少重新創建數組和copy數據,優化性能。

下一篇文章我們來看看ArrayList的其他方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容