Java 常用集合擴容機制總結
參考:java中各種集合的擴容機制記錄總結_wwwtotoro的部落格-CSDN部落格_集合的擴容機制
JAVA中的部分需要擴容的內容總結如下:
第一部分:HashMap 、HashSet、Hashtable
第二部分:ArrayList、CopyOnWriteArrayList
第三部分:StringBuffer、StringBuilder
先從以下幾個原始碼方面分析:(JDK1.8)
1、初始容量。2、擴容機制。3、同類型之間對比。
1.1 HashMap:
一、初始容量定義:預設為1 << 4(16)。最大容量為1<< 30
二、擴容載入因子為(0.75),第一個臨界點在當HashMap中元素的數量大於table陣列長度*載入因子(16*0.75=12),
則按oldThr << 1(原長度*2)擴容。
1.2 HashSet
一、初始容量定義:16。因為構造一個HashSet,其實相當於新建一個HashMap,然後取HashMap的Key。
擴容機制和HashMap一樣。
1.3 Hashtable
一、初始容量定義:capacity (11)。
二、擴容載入因子(0.75),當超出預設長度(int)(11*0.75)=8時,擴容為old*2+1。
int newCapacity = (oldCapacity << 1) + 1;
2.1 ArrayList
一、初始容量定義:10。
二、擴容:oldCapacity + (oldCapacity >> 1),即原集合長度的1.5倍。
int newCapacity = (oldCapacity * 3)/2 + 1;
2.2 CopyOnWriteArrayList:
CopyOnWriteArrayList在做修改操作時,每次都是重新建立一個新的陣列,在新陣列上操作,最終再將新陣列替換掉原陣列。因此,在做修改操作時,仍可以做讀取操作,讀取直接操作的原陣列。讀和寫操作的物件都不同,因此讀操作和寫操作互不干擾。只有寫與寫之間需要進行同步等待。另外,原陣列被宣告為volatile,這就保證了,一旦陣列發生變化,則結果對其它執行緒(讀執行緒和其它寫執行緒)是可見的。
CopyOnWriteArrayList並不像ArrayList一樣指定預設的初始容量。它也沒有自動擴容的機制,而是新增幾個元素,長度就相應的增長多少。CopyOnWriteArrayList適用於讀多寫少,既然是寫的情況少,則不需要頻繁擴容。並且修改操作每次在生成新的陣列時就指定了新的容量,也就相當於擴容了,所以不需要額外的機制來實現擴容。
3.1 StringBuffer
一、初始容量定義:16。
二、擴容:因為StringBuffer extends AbstractStringBuilder,所以實際上是用的是AbstractStringBuilder
的擴容方法,當用append(str)新增字串時,假設字串中已有字元長度為count的字串,初始長度value=16,若要新增的
字串長度(count+str.length())<=(value*2+2)則按value*2+2長度擴容,並且value=value*2+2,若(count+str.length())>(value*2+2),則按count+str.length()長度擴容,並且value=count+str.length()。下次超出時再按以上方法與value*2+2比較擴容。
private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity;
3.2 StringBuilder
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence public StringBuilder() { super(16); } private int newCapacity(int minCapacity) { // overflow-conscious code int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity;