ArrayList部分一共五篇文章了,並且引入了時間複雜度來分析,強烈建議大家一定要按順序閱讀,相關文章分別是:
2、ArrayList底層陣列擴容原理 – Java那些事兒專欄
5、ArrayList的時間複雜度 – Java那些事兒專欄(本文)
在以前的文章裡,我們已經看過了add方法的原始碼,還有一個add方法,我們看一下, public void add(int index, E element) ,從指定位置新增元素
按照下標把元素新增到指定位置,想必大家都知道,我們直接上原始碼。
老規矩,我們還是畫一畫,當執行到System.arraycopy()這個方法時
我看到有些書上寫的是依次移動元素到下一格,這種說法不夠嚴謹,所以我再強調一遍,是依次複製插入位置及後面的陣列元素,到後面一格,不是移動,因此,複製完後,arr[2],arr[3]指向對一個物件。
在程式碼執行完這一句
我們debug驗證一下。
最後,在堆記憶體中建立李莫愁這個物件,把arr[2]的引用指向它。
再debug一下
最後我們來說說ArrayLIst這個物件裡新增的時間複雜度:
如果我們不指定位置直接新增元素時(add(E element)),元素會預設會新增在最後,不會觸發底層陣列的複製,不考慮底層陣列自動擴容的話,時間複雜度為O(1) ,在指定位置新增元素(add(int index, E element)),需要複製底層陣列,根據最壞打算,時間複雜度是O(n)。
最後我們說一說讀取元素,下面程式碼是獲取List中下標為2的元素
看一下原始碼:
很簡單,讀取元素和陣列長度無關,直接從底層陣列裡去拿元素。
評論區有人說,為什麼是“李莫愁”,看樣子是不太喜歡“李莫愁”,我們可以呼叫 set(int index, E element)方法來替換。
我們看一看這個方法的原始碼
很簡單,就是往指定位置放入元素,並返回原來的元素,最後我們來畫一畫
圖中“李莫愁”已經沒有引用指向它了,JVM會在合適的時候回收它,底層陣列第2個位置已經換成了“小龍女”,我們debug驗證一下。
沒錯,已經換成小龍女了。
這是最後一期ArrayLIst原始碼分析,引入了時間複雜度,最後,我們來做個總結:
根據前幾篇文章我們可以看出來,在ArrayList中,底層陣列存/取元素效率非常的高(get/set),時間複雜度是O(1),而查詢,插入和刪除元素效率似乎不太高,時間複雜度為O(n)。
當我們ArrayLIst裡有大量資料時,這時候去頻繁插入/刪除元素會觸發底層陣列頻繁拷貝,效率不高,還會造成記憶體空間的浪費,這個問題在另一個類:LinkedList裡有解決方案,請期待後續文章講解。
查詢元素效率不高,在HashMap裡有解決方案,請關注後續文章。
下一篇:Arraylist與Vector的區別 – Java那些事兒專欄
注:本專欄文章首發於公眾號:saysayJava。所有示例程式碼均已上傳至公眾號,需要請關注下載。
如果喜歡本系列文章,請為我點贊或順手分享,您的支援是我繼續下去的動力,您也可以在評論區留言想了解的內容,有機會本專欄會做講解,最後別忘了關注一下我。
轉載無限歡迎,但請註明「作者」和「原文地址」。轉載請在文中保留此段,感謝您對作者版權的尊重。如需商業轉載或刊登,請聯絡作者獲得授權。