java集合的扩容机制

目录

    • ArrayList 和Vector扩容机制总结:
    • LinkedList没有扩容机制:
    • HashSet和HashMap扩容机制总结:
    • Hashtable扩容机制:
    • 小结:HashTable和HashMap区别
    • 小结:StringBuffer和StringBuilder:

总结一:以下就是List下的三个实现类集合ArrayList 和Vector,LinkedList扩容总结:

ArrayList 和Vector扩容机制总结:

ArrayList 和Vector,底层都是Object数组,默认加载因子都是1(元素满了才扩展容量).默认容量都是10;但是ArrayList 在jdk1.8时默认为空,当添加元素时,才初始化为10个容量。ArrayList:新容量为原容量的1.5倍,Vector:新容量为原容量的2倍.

ArrayList 默认初始容量为10,(jdk8的时候底层Object[] elementData数组初始化为{},并没有创建长度为10的数组。在add元素时才创建了10个容量。)
线程不安全,查询速度快
    底层数据结构是数组结构
    扩容增量:原容量的 0.5倍,新容量为原容量的1.5倍。
    如 ArrayList的容量为10,一次扩容后是容量为15

同样可以通过分析源码知道:
Vector:
默认初始容量为10,(jdk7和jdk8一样都初始容量为10)。
线程安全,但速度慢
    底层数据结构是数组结构
    加载因子为1:即当 元素个数 超过 容量长度 时,进行扩容
    扩容增量:原容量的 1倍,新容量为原容量的2倍。
    如 Vector的容量为10,一次扩容后是容量为20

LinkedList没有扩容机制:

LinkedList:没有扩容机制,因为其底层是双向链表结构。不存在数组的扩容一说,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好。

总结二:Set下的三个实现类集合HashSet和LinkedHashSet,TreeSet,扩容总结:LinkedHashSet,TreeSet没有数组的扩容机制。

HashSet和HashMap扩容机制总结:

HashSet和HashMap都是默认初始容量是16(jdk1.7的),但是jdk1.8做了优化,初始容量为0,第一次存元素的时候才扩容为16,加载因子是0.75,扩容为原来的2倍。而带LinkedHashSet和LinkedHashMap是链表不存在扩容的,HashSet:底层是数组+链表的结构

Set(集) 元素无序的、不可重复。
HashSet:线程不安全,存取速度快
     底层实现是一个HashMap(保存数据),HashSet:底层是数组+链表的结构,实现Set接口
     默认初始容量为16(jdk1.8及以后)(为何是16,见下方对HashMap的描述)
     加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容
     扩容增量:原容量的 1 倍,新容量为原容量的2倍
      如 HashSet的容量为16,一次扩容后是容量为32。
      因为构造一个HashSet,其实相当于新建一个HashMap,然后取HashMap的Key。
扩容机制和HashMap一样。

Map是一个双列集合:
HashMap:jdk1.8默认初始容量0,当第一次put元素的时候才扩容为16,jdk1.7是初始化容量为16
     (为何是16:16是2^4,可以提高查询效率,另外,32=16<<1 –>至于详细的原因可另行分析,或分析源代码)
     加载因子为0.75:即当 元素个数 超过 容量长度的0.75倍 时,进行扩容
     扩容增量:原容量的 1 倍,新容量为原容量的2倍
      如 HashSet的容量为16,一次扩容后是容量为32

Hashtable扩容机制:

public Hashtable() {
        this(11, 0.75f);
    }

Hashtable默认初始容量11
二、扩容加载因子(0.75),当超出默认长度(int)(11*0.75)=8时,扩容为oldx2+1。新容量为原容量的2倍+1.
int newCapacity = (oldCapacity << 1) + 1;

      
总结:

1.HashMap如果用默认构造方法的话,HashMap开始容量为0,第一次put元素的时候才扩容为16;
2.HashMap使用有参构造方法的话,HashMap容量并不是我们参数给定的大小,而是大于等于给定容量参数的 最接近 2的次幂。如我们给定容量为7,则是2的3次幂,即8容量,因为2的次幂可以通过右移快速得到。
3.扩容为原来的2n

1HashTable如果使用默认的构造方法的话,初始容量为11;
2.HashTable如果使用有参构造方法的话,初始容量即为给定的参数容量值,如3,7等就直接用了;
3.扩容为原来的2n+1

小结:HashTable和HashMap区别

第一,继承不同。
public class Hashtable extends Dictionary implements Map
public class HashMap extends AbstractMap implements Map
第二:
Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用
Hashtable,但是要使用HashMap的话就要自己增加同步处理了。
第三,Hashtable中,key和value都不允许出现null值。
在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,
即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中
是否存在某个键, 而应该用containsKey()方法来判断。
第四,两个遍历方式的内部实现上不同。
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
第五,哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
第六,Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old2+1。HashMap中hash数组的默认大小是16, 增加的方式是 old2。

小结:StringBuffer和StringBuilder:

StringBuilder和StringBuffer的初始容量都是16,程序猿尽量手动设置初始值。以避免多次扩容所带来的性能问题,默认数组容量扩充为原数组容量的2倍+2

1.StringBuilder是jdk1.5引进的,而StringBuffer在1.0就有了;
2.StringBuilder和StringBuffer都是可变的字符串。能够通过append或者insert等方法改动串的内容;
3.StringBuffer是线程安全的而StringBuilder不是,因而在多线程的环境下优先使用StringBuffer,而其它情况下推荐使用
StringBuilder,由于它更快。
4.StringBuilder和StringBuffer都继承自AbstractStringBuilder类,AbStractStringBuilder主要实现了扩容、append、
insert方法。StrngBuilder和StringBuffer的相关方法都直接调用的父类。
5.StringBuilder和StringBuffer的初始容量都是16,程序猿尽量手动设置初始值。以避免多次扩容所带来的性能问题
6.StringBuilder和StringBuffer的扩容机制是这种:首先试着将当前数组容量扩充为原数组容量的2倍加上2,假设这个新容
量仍然小于预定的最小值(minimumCapacity),那么就将新容量定为(minimumCapacity),最后推断是否溢出,若溢出,
则将容量定为整型的最大值0x7fffffff。

你可能感兴趣的:(javase,java)