1. 程式人生 > >java集合類原始碼詳解-ArrayList(5)

java集合類原始碼詳解-ArrayList(5)

上次,測試了java集合類支援遍歷方式的效率比較,今天再通過斷電除錯,去ArrayList底層的迭代器做了什麼。

首先在迭代器這裡打上斷電,(在實際中變數ArrayList最後別用迭代器,因為他很慢)

可以看到這個iterator()方法返回值是一個迭代器,函式體是return new Itr()

點選下一步。可以看到Itr是一個ArrayList裡面的一個類,從右邊類結構圖可以看到。ArrayList裡面有四個類。

ArrayList的父類abstractList裡面也有Itr這個類。

 

這裡先點開Itr這個類,裡面有哪些方法。

 

 再次點選下一步。類成員初始化。

再次點選下一步。回到return語句。

 再次點選下一步,返回到我們自己寫的程式碼裡面,開始執行hasnext()方法。

這裡再點選下一步,進入hasnext()方法。這個方法是判斷是否還有下一個元素

這裡return語句 cursor是下一個元素返回的索引,size是容器的大小。

這裡肯定不等於。返回true。

點選下一步,開始執行next()方法。

再次點選下一步,進入next()方法,這個方法是Itr內部的一個方法。這裡先會去執行checkForComodficaation()這個方法,

這個方法主要是檢查在迭代時,要迭代的容器的數量是否發生變化,如果發生變化,就拋異常

 點選下一步,這裡不會拋異常

 再次點選下一步,把下一個元素索引0,賦值給當前元素的索引i,此時i為0.

點選下一步,此時判斷索引是否大於等於了容器的大小,這裡肯定沒有。

 再次點選下一步。這裡會建立一個數組引用當前陣列,然後再次判斷下標 i 是否大於等於陣列長度。

為什麼要這樣呢?因為這個新的element陣列,是引用的之前我們的10萬大小的陣列,如果在迭代過程中增加了元素,下標 i 會增加,因為資料增加了,資料在數組裡面對應是有下標的,也要多,那麼肯定會比之前沒增加資料的資料最大長度大或者相等。

如果出現這種情況,說明在迭代過程中,我們向容器裡面新增元素,所以丟擲異常。

再次點選下一步。到這一步,馬上我們就能return要遍歷的第一個元素了,所以為下一次遍歷做準備

cursor+1

 再次點選下一步,我們這裡返回第一個元素,藉助lastRet這個變數,這個變數初始值是最後一個變數索引,值為-1,

我們把當前要遍歷的索引賦給它,然後返回這個陣列即 elementData[0] 這樣就完成了第一個元素的訪問。

好了,ArrayList的迭代器方法和內部一個Itr類原始碼跟蹤就結束了,下面再來看看get()這個方法,同樣 打上一個可愛的斷點。

點選下一步。get()方法是返回指定位置上的元素,從0開始,這裡可以清晰看到get()方法,比 之前的next()方法簡單多了,內部沒那麼多東西。

再次點選下一步,執行範圍檢查函式。如果索引大於等於了容量的實際儲存的資料數量

比如一個長度為10的陣列,裡面有10個數 分別是1到10,此時的size是10,那麼索引位9是最大的,index=9當然可以

但是index>=10,是絕對不可以的。或者數組裡面只有1到5,此時size=5,陣列最大容量為10,你獲取index=4當然可以,但是獲取index=5,此時這個位置是沒有數的,所以會拋異常。

 再次點選下一步,臥槽,此時不是應該返回一個element[index]麼,這是什麼!為什麼還傳個索引過去?

當我們再次點選下一步,會發現這是一個方法。此時的E是student,

這個方法其實就是返回一個強轉的student型別的element[index]陣列。

這裡可以看出這個操作的封裝力度很強,連強轉都要封裝。

 

好了,到此為止,就告一段落了。

後續樓主會繼續學習集合類的原始碼,另外部落格什麼地方寫錯,請指出,大家一起學習進步!!