Java 常用集合扩容机制总结
参考: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;