參考:java中各種集合的擴容機制記錄總結_wwwtotoro的博客-CSDN博客_集合的擴容機制
JAVA中的部分需要擴容的內容總結如下:
第一部分:HashMap 、HashSet、Hashtable
第二部分:ArrayList、CopyOnWriteArrayList
第三部分:StringBuffer、StringBuilder
先從以下幾個源碼方面分析:(JDK1.8)
1、初始容量。2、擴容機制。3、同類型之間對比 4、最大容量
為什么要-8:
因為自己作為數組,除了存儲數據本身以外,還需要32 bytes的大小來存儲對象頭信息。
Java每個對象都包含了對象頭,HotSpot虛擬機中對象頭的大小不會超過32 bytes,所以最大容量減8才不會溢出。
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;