2.10 HashMap & ConcurrentHashMap
less than 1 minute read
2.10.1 HashMap
put()
putVal()
- 无碰撞, 插入操作
- 碰撞
hash
& key
一致, 覆盖操作
p.next
找队尾, 插入
- 判断是否需要扩容, 即如果
size
大于capacity * LOAD_FACTOR
, 即当前大小大于容量*负载因子, 默认是16 * 0.75, 即12
2.10.2 ConcurrentHashpMap
put()
tryLock()
获取segment
分段锁
- 无碰撞, 插入操作
- 碰撞
hash
& key
一致, 覆盖操作
- 否则插入队尾
- 扩容: 通过CAS设置
sizeCtl
和transferIndex
, 协调多线程扩容;核心是transfer()
调整节点位置
2.10.3 hash冲突解决方式
- 开放定址法, 出现冲突则再hash, 产生新的hash值, 直到没有冲突, 如
ArrayMap
, 再hash包含以下三种:
- 线性探测法再hash, 发生冲突, 顺序查找下一单元, 直到有空单元或遍完全表
- 二次探测再hash,
- 伪随机探测再hash
- 再hash法, 遇冲突使用别的hash算法再hash
- 链地址法, 出现冲突则放到key对应的链表, 如
HashMap
- 建立公共溢出区, 将hash表分为基本表和溢出区, 冲突一律放到溢出区
2.10.3 HashMap & ConcurrentHashMap & HashTable区别
- HashTable: 数组+链表实现, key & value均不能为null, 线程安全但对整表加锁, 效率低; 扩容: newSize = 2*oldSize+1
- HashMap: 数组+链表实现, 线程不安全; 扩容: newSize = 2*oldSize
- ConcurrentHashMap: 分段数组+链表实现; 线程安全, 分段加锁, 且读无锁