ArrayList初始化 - Java那些事兒
ArrayList部分一共五篇文章了,並且引入了時間複雜度來分析, 強烈建議大家一定要按順序閱讀,本文是第1篇。
前些天的文章,反覆的畫圖,不停的重複,就是想讓大家理解,物件在記憶體中是什麼樣的。也是為今天的及以後的講解打下基礎。如果要說大家在寫Java程式碼的時候哪個類用得最多,我想除了String,基本上就是ArrayList了吧,那今天我們說說ArrayList。
首先ArrayList是一個普通的類,我們來看一段程式碼:
首先:執行List<Person> list1 = new ArrayList<>();當看到new這個關鍵字的時候,我們腦袋裡應該第一印象就是這貨在堆記憶體開闢了一塊空間,好我們再來畫一畫。
注:常量池位於方法區,方法區位於堆記憶體,前面沒涉及到,所以沒畫方法區,現在補上
好,既然是new出來的,那我們直接從建構函式入手,看一下建構函式做了什麼。
很簡單,就一行程式碼,繼續看一下,this.elementData和DEFAULTCAPACITY_EMPTY_ELEMENTDATA分別是什麼
紅框裡的內容是不是似曾相識?是的,和String一樣,底層是陣列,唯一的區別是String底層是char[]陣列(忘了的可以複習一下,傳送門:
注:static修飾的變數,常駐於方法區,我們不需要new,JVM會提前給我們初始化好,這個特性在實際開發過程中,經常拿來做快取。在
一文中,我們文中Integer的快取就是最好的例子。static變數又叫類變數,不管該類有多少個物件,static的變數只有一份,獨一無二。
fianl修飾的變數,JVM也會提前給我們初始化好。
transient這個關鍵字告訴我們該物件在序列化的時候請忽略這個元素,後續我們會講序列化,這兒先跳過。
繼續執行:List<Person> list2 = new ArrayList<>();
ArrayList這個類的作者真是好貼心,new的時候連快取都考慮到了,為了避免我們反覆的建立無用陣列,所有新new出來的ArrayList底層陣列都指向快取在方法區裡的Object[]陣列。
繼續執行Person person1 = new Person("張三")
繼續,執行list1.add(person1),不多說,看原始碼ArrayList是怎麼處理add的。
我們先看ensureCapacityInternal方法,方法裡有個引數是size,看們先看一下這個size從哪來的。
原來是一個成員變數,相信大家看到size一猜就知道大概是幹嘛的了吧。好,我們在圖裡的ArrayList物件裡補上它,size是int基本資料型別,成員變數初始化的為0。
繼續往下看
ensureCapacityInternal方法是在add裡面呼叫的。
再看grow方法
跟進到Arrays這個工具類,很簡單
再看copyOf()方法 //java學習交流:737251827 進入可領取學習資源及對十年開發經驗大佬提問,免費解答!
最後我們來看一下System.arraycopy()方法,好奇怪,這個方法只有定義,卻沒有實現,方法用了一個native來修飾。native的方法,是由其它語言來實現的,一般是(C或C++),所以這兒沒有實現程式碼。這是一個陣列拷貝方法,大家還在寫for迴圈拷貝陣列嗎?以後多用這個方法吧,簡單又方便還能獲得得更好的效能。
注:native方法,我們會後續會講解,我們先關注本章內容。
由於陣列內容目前為空,相當於沒有拷貝。折騰了這麼久,原來只是為了建立一個預設長度為10的Object[]陣列,有些朋友說,直接new不就行了,這麼費勁,其實這裡面大有文章,別急,稍後會說,繼續畫圖。
再回過頭來看,add()這個方法,繼續往下執行:
很簡單,size現在是0,就是把傳進來的這個e(這裡是person1),放到list1的elementData[]下標為0的陣列裡面,同時size加1,老規矩,上圖。
注意看紅框裡,雖然我們list1裡的elementData陣列的長度是10,但是size是1,size是邏輯長度,並不是陣列長度。
現在debug一下,驗證我們圖裡的內容:
好的,執行一下本文開始那段程式碼,看結果:
順便看一看size()方法的原始碼:
有人說,呀,就一個元素,在堆記憶體中佔了10個位置,好浪費呀,沒辦法,你要享受ArrayList的便利與豐富的API,就得犧牲一下空間作為代價。
《ArrayList底層陣列擴容原理 - Java那些事兒》
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70010294/viewspace-2849120/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ArrayList初始化 – Java那些事兒Java
- Arraylist與Vector的區別 - Java那些事兒專欄Java
- ArrayList的時間複雜度 – Java那些事兒專欄時間複雜度Java
- ArrayList的時間複雜度 - Java那些事兒專欄時間複雜度Java
- ArrayList底層陣列擴容原理 - Java那些事兒專欄陣列Java
- Java字串那些事兒Java字串
- 雲原生java的那些事兒Java
- 物件導向 - Java那些事兒物件Java
- Java日誌框架那些事兒Java框架
- Java中的陣列 - Java那些事兒Java陣列
- babel那些事兒Babel
- PHP那些事兒PHP
- OAuth那些事兒OAuth
- Git那些事兒Git
- 談談java入門的那些事兒Java
- 寫在專欄前-Java那些事兒Java
- 讓人疑惑的Java程式碼 – Java那些事兒Java
- 說說Java裡的equals(中)- Java那些事兒Java
- Java自動裝箱/拆箱 - Java那些事兒Java
- 讓人疑惑的Java程式碼 - Java那些事兒Java
- webpack的那些事兒Web
- 聊聊viewport那些事兒View
- Ubuntu的那些事兒Ubuntu
- C語言那些事兒C語言
- MySQL優化那些事兒MySql優化
- https的那些事兒HTTP
- PHP 閉包那些事兒PHP
- 字元編碼那些事兒字元
- 面試的那些事兒--01面試
- 網路安全那些事兒
- TCP 的那些事兒(下)TCP
- TCP 的那些事兒(上)TCP
- 依賴注入那些事兒依賴注入
- Rest API 的那些事兒RESTAPI
- IT專案管理那些事兒專案管理
- Hadoop搭建那些事兒Hadoop
- 時間複雜度 – Java那些事兒專欄時間複雜度Java
- 時間複雜度 - Java那些事兒專欄時間複雜度Java