java Collection接口和Map接口知识点总结

        最近写代码,感觉对jdk中Collection和Map中的实现方式和原理有些遗忘,为了在写代码的时候让代码更加简介和让性能更加优秀,所以我先必须了解其中容器增长方式和原理,HashMap,如果那个Node桶存放的数据大小大于等于8,就会采用红黑树存储。

工具:starUML、IDEA

jdk版本:jdk1.8.0_102

(一)  先贴上一张类图:

辛苦制作的UML类图

(二) 其中Collection和Map部分实现中实现参数。

1、 全局实现的参数:

新容量大小/原容器大小 = N/O

 x = 没有该值

(一)
 Collection
 ListSet
 ArrayListAttributeListRoleListLinkedListVectorStackHashSetTreeSetLinkedHashSet
实现方式

Object[]

数组

Object[]

数组

Object[]

数组

Node<E>

双向链表

Object[]

数组

Object[]

数组

HashMap<E,Object>

 

NavigableMap<E, Object>HashMap<E,Object>
默认容器大小101010x101016x16
扩充容量方式System.arraycopySystem.arraycopySystem.arraycopyxSystem.arraycopySystem.arraycopy(Node<K, V>[])new Node[newCap]x(Node<K, V>[])new Node[newCap]
N/O1.51.51.5x2(默认,值在初始化的第二个参数可设置)2默认,值在初始化的第二个参数可设置)2x2
负载因子111x110.75fx0.75f
默认门阀记载因子*容量大小记载因子*容量大小记载因子*容量大小x记载因子*容量大小记载因子*容量大小

如果使用无参构造方式,默认门阀为“默认加载因子”*"默认cap大小".

如果使用其他构造函数,门阀值初始为

将该初始因子-1的值写成机器码,从最高位(从左往右除符号位的第一个1)开始,右边所有位变1的值。

x

如果使用无参构造方式,默认门阀为“默认加载因子”*"默认cap大小".

如果使用其他构造函数,门阀值初始为

将该初始因子-1的值写成机器码,从最高位(从左往右除符号位的第一个1)开始,右边所有位变1的值。

线程安全x

 

(二)
 Map
  
 HashMapLinkedHashMapHashtableWeakHashMapTreeMapEnumMapAttributesConcurrentHashMapProperties
实现方式

Node<K, V>[]

(根据key的hash值和长度来决定选择那个桶index)有hashValue,next的链表结构(这里面定义了TreeNode extend LinkedHashMap.Entry)

LinkedHashMap.Entry<K, V> 双向链表实体,继承HashMap.Node<K, V>

Entry<K,V>[]

是HashMap的安全实现

Entry<K,V>[]

是继承WeakReference实现弱引用,减少在内存中存活时间,节省内存。

 

Entry<K, V>

有right,left,parent的map结构

Object []

数组

Map<Object, Object>,使用的HashMap实现

Node<K,V>[]

数组

Entry<K,V>[]

是HashMap的安全实现,是继承于HashTable

默认容器大小16x1116x动态111611
扩充容量方式(Node<K, V>[])new Node[newCap]xnew Entry<?, ?>[newCapacity](Node<K, V>[])new Node<?, ?>[newCap]xx(Node<K, V>[])new Node[newCap](Node<K, V>[])new Node<?, ?>[n << 1]new Entry<?, ?>[n]
N/O2x2  另外加12xx222 另外加1
负载因子0.75fx0.75f0.75fxx0.75f0.75f0.75f
默认门阀

如果使用无参构造方式,默认门阀为“默认加载因子”*"默认cap大小".

如果使用其他构造函数,门阀值初始为

将该初始因子-1的值写成机器码,从最高位(从左往右除符号位的第一个1)开始,右边所有位变1的值。

x记载因子*容量大小记载因子*容量大小xx

如果使用其他构造函数,门阀值初始为

将该初始因子-1的值写成机器码,从最高位(从左往右除符号位的第一个1)开始,右边所有位变1的值。

如果使用其他构造函数,门阀值初始为

将该初始因子-1的值写成机器码,从最高位(从左往右除符号位的第一个1)开始,右边所有位变1的值。

记载因子*容量大小
线程安全

2、线程安全构造函数和门阀与N/O的关系详细说明: 

新容量大小/原容器大小 = N/O

新门阀/老门阀 = NT/OT

 x = 不存在

  i = 输入值

oldCap = 老容器大小

oldCap/2(取整) = oldCap >> 1 

{2^n}=  满足2的n次方值大于i条件2的n次方的最小值

动态 = 表示它没有实现,需要传入一个实现的对象,按照对象来使用

1) 线程安全:

线程安全(一)
 VectorStack(继承与Vector)
 初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT
默认容器大小10xx2x10xx2x
只有initialCapacity参数值ixx2xxxxxx
有initialCapacity,loadFactor参数的值ixx这儿没有loadFactor参数,有capacityIncrement参数,每次增加capacityIncrementxxxxxx

 

线程安全(二)
 Stack(继承与Vector)HashtableConcurrentHashMapProperties
 NT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT
默认容器大小x110.75f82 倍另外单独+12160.75fx22110.75f82 倍另外单独+12
只有initialCapacity参数值xi0.75f

i

* 0.75f

2 倍另外单独+123i/2 + 10.75f

i

* 0.75f

22i0.75f

i

* 0.75f

2 倍另外单独+12
有initialCapacity,loadFactor参数的值xiii(容量) *i(负载因子)2 倍另外单独+12{2^i/loadFactor}ii(容量) *i(负载因子)22iii(容量) *i(负载因子)2 倍另外单独+12

2)线程不安全:

线程不安全(一)
 ArrayListAttributeListRoleListLinkedList
 初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT
无参构造函数容器大小10xoldCap1.5x10xoldCap1.5x10xoldCap1.5xxxxxx
只有initialCapacity参数值ixoldCap1.5xixoldCap1.5xixoldCap1.5xxxxxx
有initialCapacity,loadFactor参数的值ixoldCap1.5xixoldCap1.5xixoldCap1.5xxxxxx
线程不安全(二)
 HashSet(数据保存是通过HashMap实现的)TreeSetLinkedHashSet(继承HashSet)HashMap
 初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT
无参构造函数容器大小160.75f1222xxxxx160.75f1222160.75f1222
只有initialCapacity参数值{2^n}0.75f

{2^n}

* 0.75f

22xxxxx{2^n}0.75f

{2^n}

* 0.75f

22{2^n}0.75f

{2^n}

* 0.75f

22
有initialCapacity,loadFactor参数的值{2^n}i

{2^n}

* 0.75f

22xxxxx{2^n}i

{2^n}

* 0.75f

22{2^n}i

{2^n}

* 0.75f

22

 

线程不安全(三)
LinkedHashMapWeakHashMapTreeMapEnumMapAttributes(数据用HashMap来保存)
初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT初始容量负载因子门阀N/ONT/OT
160.75f1222160.75f1222xxxxx动态动态动态动态动态160.75f

{2^n}

* 0.75f

22
i0.75f

{2^n}

* 0.75f

22{2^n}0.75f

{2^n}

* 0.75f

22xxxxx动态动态动态动态动态{2^n}0.75f

{2^n}

* 0.75f

22
ii

{2^n}

* 0.75f

22{2^n}i

{2^n}

* 0.75f

22xxxxx动态动态动态动态动态xxxx

 

 

 补充描述:这里面有些很复杂,详细还是得去研究源码,而且,每个jdk版本的实现的方式不一样,建议有时间详细看源码,了解其中原理。最重要的是HashMap,TreeMap,Hashtable,ConcurrentHashMap这些详细查看很有用, 这个其中还常使用到CAS。

(三) 知识点总结:

HashMap,虽然存储数据是通过key-value的形式存储的,但是,它内部为了提高查询效率,使用的key的hash值,构建数组对象链。先是数组,称作“桶”,通过hash值来判断放那个桶,桶的数量就是上面的cap。每个桶存放的数据小于8个的时候,是采用简单的对象表,如果那个Node桶存放的数据大小大于等于8,针对该桶的数据就会采用红黑树存储。

ConcurrentHashMap在这个版本实现和HashMap内容差不多,只是增加了线程安全的操作,其中加载因子只是在容器初始化的时候和cap通过cap/loadFactor + 1向上取2^n的整数,还有这个版本Segment只有在JAVA对象流进行序列化和反序列化中使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值