集合(一)扒掉ArrayList的外衣

集合(一)扒掉ArrayList的外衣

集合(二)走進LinkedList的內心 

集合(三)HashMap背後的故事

ArrayList是什麼?

 顫抖的小手敲開門ArrayList的大門,發現她竟然是Object[] elementData數組。

構造函數

我們在使用集合的時候都知道集合長度是隨着插入刪除變化的,而在創建數組時時需要指定長度的,那ArrayList是如何做到長度可變數組呢

我們發現ArrayList有兩個構造函數,一個無參(我們經常用)一個有參(傳入一個int值,這個int就是初始數組的長度)

無參構造會在我們插入數據時候默認數組長度爲10,當我們在創建時指定了長度,就是初始化數組的長度。

這裏有一個關鍵字transient,這個關鍵字的作用就是在序列化時忽略該變量,ArrayList是集成Serializable的可以序列化反序列化操作的。

add數據 

我們在使用集合時可以無限的添加數據的,這默認長度10,ArrayList是如何做到擴容的

 這10只是數組的長度,我們集合的長度是根據size變量來的,集合會在插入數據是size+1然後去和數據的長度比較,如果超出了最大容量,就會創建一個長度爲10+10/2(JDK8的操作)長度的數組,然後把原數組的內容複製到新數組中,這就完成了擴容。

ArrayList在添加一個數據時做了三件事:

  1. size+1是否在集合容量之內ensureCapacityInternal(English是不是很吊),其實就是判斷是否需要擴容;
  2. 數據添加到索引爲size+1這個位置;
  3. 返回true。

看源碼會知道,擴容就是擴大之前的容器長度向右移1位。大家也可能注意到默認分配的數組大小爲integer的最大值-8,這是因爲

一些vm在數組中保留一些頭字。嘗試分配較大的數組可能會導致OutOfMemory錯誤:請求的數組大小超過了虛擬機限制(百度翻譯- -)。

ArrayList又是如何在指定索引處添加數據呢

集合在指定index插入數據,首先會複製數組index開始到最後一個值的數據,然後在index+1位置開始放,騰出index的位置給新值插入,當然這裏面也要先判斷容量問題。(如下圖在3的位置插入一個新值)

remove刪除數據 

我們知道在我們遍歷ArrayList的時候刪除數據會報錯java.util.ConcurrentModificationException ,why?

 移除數據的操作也是copy指定位置+1之後的數組移動到指定位置,直接看圖說話。

這就也可解釋爲什麼遍歷時移除數據會報錯,5覆蓋了4的位置,那麼5就無法被遍歷到了。當然如果我們從大到小遍歷就不會出現這個問題了。

 

ArrayList在增刪時候需要去copy數據,如果超出最大數組長度還要去擴容什麼的,所以說ArrayList的增刪效率是低的。

ArrayList的內存連續性使其遍歷速度相對較快,所以查找就快。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章