集合扩容底层实现

2019-10-11  本文已影响0人  Arvesynden

1、List:有序可重复

(1)ArrayList:数组实现

       初始容量:10      负载因子:1        扩容:1.5倍         

       创建数组的时候 长度是0;第一次添加元素的时候  初始化数组的长度10

       底层调用Arrays.copyof()

(2)LinkedList:线性链表(1.5之前采用单向链表,1.5之后采用双向链表)

              链表结构中的每一个元素 就叫做node对象

          由于它的底层是用双向链表实现的,所以它对元素的增加、删除效率要比ArrayList好;

          它是一个双向链表,没有初始化大小,也没有扩容的机制,就是一直在前面或者后面新增就好。

(3)Vector:线程同步数组

当扩容因子大于0时,新数组长度为原数组长度+扩容因子,否子新数组长度为原数组长度的2倍。

(4)Stack:栈

初始容量:10      调用vector的扩容机制扩容


2、set:无序不重复

      set集合就是map集合的一部分(key部分)

(1)HashSet:数组(16)+链表(单向链表)+树(红黑树)

       HashMap中k-v中的k部分

       初始容量:16      负载因子:0.75        扩容:2倍

       扩容实现:

             首先计算扩容大小:存储容量*2===>16*2=32; 申请线性表表空间,长度为32; 重新计算原来的数据在新数组中的位置,并进行复制;

      hashset如何去重的:

               hash值不同的两个元素 一定不是同一个元素 先判断hash值,后比较equals方法(地址)

(2)TreeSet:红黑树

      TreeMap中k-v中的k部分,有序不可重复

       排序方式:自然排序

               如果是数值:值的大小 默认升序的

               如果是字符串:字典顺序进行排序的

      初始容量:16      负载因子:0.75        扩容:2倍

扩容实现:

首先计算扩容大小:存储容量*2===>16*2=32;    申请线性表表空间,长度为32;    重新计算原来的数据在新数组中的位置,并进行复制;

   hashset如何去重的:

               hash值不同的两个元素  一定不是同一个元素

先判断hash值,后比较equals方法(地址)


3、Map:键值对

(1)HashMap:数组(16)+链表(单向链表)+树(红黑树)

初始容量:16      负载因子:0.75        扩容:2倍

扩容实现:同上的HashSet

HashMap如何去重的:同上的HashSet

             

链表和树的转换:

链表结构转换为树结构的最大阀值:8(1.8之后的)

树结构转换为链表结构阀值:6

因为是一个单向链表(8)所以查询的时候性能低,在1.8之后做了一个优化,当链表的  深度超过8的时候就将链表转换为树结构。

HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸。

(2)TreeMap

     同上面的TreeSet

初始容量:11      负载因子:0.75        扩容:2倍

(3)HashTable

初始容量:11      负载因子:0.75        扩容:2倍+1

扩容实现:同上的HashSet

HashMap如何去重的:同上的HashSet

Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模

(4)ConCurrentHashMap

          既可以做到线程安全 又可以保证性能

          采用:分段线程锁+读写锁

上一篇下一篇

猜你喜欢

热点阅读