HashMap
继承 接口
|
|
实现了Map的接口
常数
|
|
- default initial capacity必须是2的幂次
- bin中元素数量默认超过8时从链表转换成红黑树
内部类
|
|
hash和key由final修饰;hashCode值由key和value的hashCode值异或获得。
|
|
|
|
补充红黑树:自平衡二叉查找树,O(logn)时间内查找插入和删除
性质
- 节点是红色或黑色。
- 根是黑色。
- 所有叶子都是黑色(叶子是NIL节点)。
- 每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)
- 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。
hash
|
|
计算key的hash值时,16位右位移异或混合即混合高位与低位,加大随机性
Fields
|
|
table被allocate时,长度总是2的幂次
构造函数
|
|
构造函数可传入参数有初始大小和负载因子,默认值分别为16和0.75。
get
|
|
table不为null,长度大于0且Node映射所在bin不为null时进行操作:
get(key)返回null值并不一定代表map不包含key的映射,也可能有key对于null的映射
使用(n-1)&hash计算到key映射的bin的下标(n-1为全1,与后即可对应到bin的位置),first指向bin中第一结点并比较key是否相等;不相等则依次比较next结点直到链表尾部,比较时需先判断时红黑树结点,相等即返回指向结点;比较都不相等则返回null
put
|
|
table为null或者table长度为0时先扩容resize
Node映射所在bin为null时,直接新建赋值新的Node;否则则bin的第一个结点存在
当第一个结点存在且key相同时,将value替换为新Node的value,并返回旧的value;当第一个结点存在且key不同且结点为红黑树的结点时,put为红黑树结点;当第一个结点存在且key相同且不为红黑树结点时,遍历链表上结点并比较key,同时记录链表上结点数量;当链表中某一结点key相同时,记录下该结点并跳出循环替换value;当遍历至链表尾部,以新的结点插入;如果结点数量超过树化阈值时,转化为红黑树
resize
table为null时,初始化为DEFAULT_INITIAL_CAPACITY大小;否则,扩容为2倍大小,每个bin中的元素要么仍然位于原来的位置,要么在新的table中以2的幂次位移进行移动
ConcurrentHashMap
继承 接口
|
|
常数
基本同HashMap
内部类
|
|
hash和key由final修饰,val和next由volatile修饰
Spread
|
|
访问table
|
|
volatile访问table[i]
CAS更新table[i]的首结点
volatile设置table[i]
构造函数
|
|
get
|
|
使用spread计算key的hash值
当table不为null,长度大于0且元素所在table处不为null时继续操作:
当第一个结点key相同时,返回value;否则遍历链表,key相同时返回value;直至遍历至链表尾部,返回null
put
|
|
ConcurrentHashMap不允许key或者value为null
table为null或者table长度为0时初始化table
通过volatile访问到元素所在table的bin处若为null,则CAS更新table处bin为新的Node,bin为空时不需要加锁;
元素所在bin不为null时,对第一个元素进行synchronized操作,并再次volatile访问确认第一个结点是否发生了变化。遍历链表,如果key相同则替换value值并跳出遍历;直至遍历至链表尾部,插入新的Node;如果第一个结点是红黑树结点,则以红黑树结点插入。遍历链表时记录结点个数,如果大于TREEIFY_THRESHOLD则转换成红黑树。