從今天開始從源碼去學習一些Java的經常使用數據結構,打好基礎:)html
jdk版本:1.8.0數組
首先看其構造方法:安全
第一種支持初始化容量大小,其中聲明一個對象數組,賦值給this.elementdata數據結構
第二種無參構造函數,即不指定初始容量大小,則默認賦值this.elementdata爲一個空的對象數組,可是由註釋能夠看到其無參構造實際上初始容量爲10多線程
在elementData的註釋中也說了該變量是實際存儲Arrylist數據的存儲結構,任何空的arraylist,當第一次被調用add放進元素時,將會擴充容量爲default_capacity也就是10函數
看看其add方法,由於arraylist也是有序的,所以加入的元素在列表尾部,在添加元素以前,調用ensureCapacityInternal,確保內部容量大小學習
在ensureCapacityInternal中將判斷當前的elementdata的值是否爲空數組,若爲空則賦值minCapacity爲默認容量和入口參數minCapacity的較大值,而後進一步調用ensureExplicitCapacity明確容量大小this
在ensureExplicitCapacity中,modCount自增,判斷當前最小容量和arraylist的實際元素個數差值若大於零,則調用grow函數來進行實際的容量擴充spa
擴容函數grow先取到當前arraylist的實際長度,而後將其擴大1.5倍,而後判斷該值和最小容量的大小,若擴充1.5倍小於所須要的最小容量,則賦值新的容量爲須要的最小容量,此時並判斷是否產生溢出狀況,也就是註釋裏面的overflow conscious mode的含義,因此arraylist不是無限擴容,看下其max_array_size的值.net
數組最大值爲integer.max_value-8,也就是2的31次-1-8
至於爲何要-8,這裏有些vm要存儲其最大值的大小須要八個字節,以下圖所示
若是擴充的新容量比max還大,則調用hugeCapacity,判斷最小的容量和2的31次-1的大小,若大於則賦值max_value,不然說明此時最小容量介於max_value-8和max_value之間,則賦值爲max_value-8
而後調用Array.copyof將舊的arraylist中的值拷貝到新的擴充後的arraylist中,因此默認空數組的add操做後容量即爲10
能夠傳遞任何實現了Collection接口的類,其調用collection的toarray方法返回一個對象數組,也就是將集合中的元素以對象數組形式返回,toarray的註釋裏也說明了這個方法是array和collection的橋樑
爲了防止重寫toArray方法返回的並非對象數組,所以這裏判斷一下elementData的類是不是對象數組,若是不是的話,則將element中的數組copy到對象數組中
好比有MySubClass是MyClass的子類。 Collection<MyClass> myCollection; //myCollection裏有不少元素。 Collection<MySubClass> mySubCollection; //mySubCollection裏有不少元素。 ArrayList<MyClass> myList = new ArrayList<MyClass>(myCollection); 也能夠: ArrayList<MyClass> myList = new ArrayList<MyClass>(mySubCollection);
意思就是這裏用extends e,來指定定義一個父類的arraylist,則其全部子類的集合都能放進該父類的arraylist,從而編譯器纔可以知道放入的元素都是知足?也就是,初始定義arraylist的類型聲明
上面遺留了一個modcount++的自增操做的解釋,看一下jdk對modcount的解釋
該參數是對arraylist容量大小修改的次數,也就是刪減元素改變大小時可能會使正常的迭代過程出現錯誤,那麼針對單線程而言,不存在又讀又寫,但在多線程狀況下,可能存在讀寫同時進行的操做,參考知乎一個很精簡明確的答案,看完真的是一目瞭然,若是結構發生變化則拋出ConcurrentModificationException
經過調用上面這個方法來判斷是否結構發生變化,調用add remove時都將修改modcount,經過迭代時先保存一份modcount,若迭代過程當中再取modcount和保存的值不等則拋出異常
①.初始不指定容量時設置爲10
②.每次擴充爲實際長度的1.5倍與所需最小容量比較
③.arraylist是非線程安全的
④.其最大值爲2的31次-1
⑤.爲避免連續擴容消耗內存,能初始化容量大小盡可能指定容量
⑥.爲啥會非線程安全,由於方法內部並不是原子操做
參考:
https://zhuanlan.zhihu.com/p/72296421 hashmap
https://zhuanlan.zhihu.com/p/73283922 linkedhashmap
https://zhuanlan.zhihu.com/p/72463637 hashset
https://zhuanlan.zhihu.com/p/72156592 arraylist
https://www.jianshu.com/p/f174d49b391c