ArrayList部分一共五篇文章了,並且引入了時間複雜度來分析,強烈建議大家一定要按順序閱讀,本文是第2篇,相關文章分別是:
再次強調,ArrayList是一個普通的類,如果我們開心,可以自己寫一個。
ArrayList初始化 - Java那些事兒專欄 文章發表後,評論區有人問如下問題。
我們先回顧一下之前的所說過的陣列,話不多說,上程式碼:
老規則,我們繼續畫一畫,加深一下印象,上圖:
這個圖我們去掉了ArrayList初探 - Java那些事兒專欄 一文圖裡那些無用的細節(方法區,常量池等),方便大家看起來清晰,我們用eclipse的debug功能看一下,看是否與我們圖上畫的一致
再看一下執行結果,也在我們期望中。
好,我們改一下程式碼,再往陣列裡加新增一個叫“周八”的person物件
執行一下
看到了傳說的中陣列下標越界異常。在Java中,陣列一但在堆記憶體中建立,長度是固定的。
既然是固定的,那我們要往陣列裡加一個“周八”使用者怎麼辦?沒辦法,只能重新new長一點的新的陣列,把原來陣列的元素複製過去,好吧,開始寫程式碼吧,相信大家都會寫
把老陣列的元素迴圈一下,賦值給新的陣列,很簡單也很清晰。debug看一下
“周八”已經有了。以上程式碼雖然簡單,但還不是最優雅的,老鳥一般會這麼寫,該段程式碼執行結果和上面那段程式碼一樣。
再畫個圖加深一下印象吧:
此圖已用盡我洪荒之力,希望大家以後多想想物件在堆記憶體中的樣子。不枉我一片苦心呀。
看到System.arraycopy()方法是不是似曾相識呢?我們在ArrayList初探 - 知乎專欄 一文中提了一下,相信看到這裡,大家都知道ArrayList裡的底層陣列擴容是怎麼實現的了吧。在ArrayList初探 - 知乎專欄 一文中,我們知道當ArrayList如果不指定構造個數的話,第一次往裡面新增元素時底層陣列會初始化一個長度為10的陣列,我們再回顧一下昨天的原始碼,再來看一下ArrayList裡的原始碼,當新增第11個元素時
再看grow()方法
這兒有一段程式碼:int newCapacity = oldCapacity + (oldCapacity >> 1),>>是移位運算子,相當於int newCapacity = oldCapacity + (oldCapacity/2),但效能會好一些。
本文開始那個問題,到這兒就解決了,這就是陣列的擴容,一般是oldCapacity + (oldCapacity >> 1),相當於擴容1.5倍。
看到這裡,相信在以後的面試中,面試官再問陣列和ArrayLIst的區別的時候,大家應該有了自己的理解,而不是去背面試題了。
ArrayList還提供了其它構造方法,我們順便來看一下。
我們再看一下原始碼,好簡單:
當我們在寫程式碼過程中,如果我們大概知道元素的個數,比如一個班級大概有40-50人,我們優先考慮List<Person> list2 = new ArrayList<>(50)以指定個數的方式去構造,這樣可以避免底層陣列的多次拷貝,進而提高程式效能。
注:本專欄文章首發於公眾號:saysayJava。所有示例程式碼均已上傳至公眾號,需要請關注下載。
如果喜歡本系列文章,請為我點贊或順手分享,您的支援是我繼續下去的動力,您也可以在評論區留言想了解的內容,有機會本專欄會做講解,最後別忘了關注一下我。
轉載無限歡迎,但請註明「作者」和「原文地址」。轉載請在文中保留此段,感謝您對作者版權的尊重。如需商業轉載或刊登,請聯絡作者獲得授權。