标签:nbsp 如何 entry 个数 超过 结构 次数 code put
1.基于哈希原理,存储key-value键值对(Entry)的集合。在JDK1.8以前数据结构是一个数组+链表,在JDK1.8以后是一个数组+链表+红黑树。(key,value,hash,next)
2.put方法原理:1)通过哈希函数计算key,得到哈希值;通过哈希值以及数组的长度,得到Entry的位置,即table的下标。index = HashCode(Key) & (Length - 1)
2)遍历此下标下的链表,如果不存在相同key,即添加新的Entry,否则更新value值。
3.get方法原理:1)通过哈希函数计算key,得到哈希值;通过哈希值以及数组的长度,得到Entry的位置,即数组的下标。
2)遍历此下标下的链表,如果存在相同key,即返回Entry。
4.在链表上插入新的Entry时,使用的是头插法,因为hashMap的发明者认为,后插入的被查找的可能性比较大。
5.默认初始长度是16,每次扩展,必须是2的幂次方,理由是:为了服务于从key映射到index的哈希算法。
6.在插入元素过多时,需要进行resize,resize条件是HashMap.Size >= Capacity * LoadFactor。
7.resize方法原理:1)扩容--创建一个新的Entry数组,长度是原数组的两倍
2)transfer方法--遍历原Entry数组,把所有的Entry重新Hash到新数组。为什么要重新Hash呢?因为长度扩大以后,Hash的规则也随之改变。
8.非线程安全,在并发插入时,有可能出现带环链表,让下一次读操作,进入死循环。
1.ConcurrentHashMap是一个二级哈希表。在一个总的哈希表下面,有若干个子哈希表。
2.采用了锁分段技术,每个Segment各自持有一把锁。在保证线程安全的同时降低了锁的粒度,让并发操作效率更高。
3.不同Segment的写入是可以并发执行的。同一Segment的写和读是可以并发执行的。
4.put方法原理:1)通过key计算哈希值
2)通过哈希值,定位到segment。
3)获取segment锁
4)再次通过哈希值,定位到segment中数组的具体位置
5)插入或覆盖hashEntry对象
6)释放锁
5.get方法原理:1)通过key得到哈希值
2)通过哈希值,定位到segment。
2)再次通过哈希值,定位到segment数组中具体位置
6.如何保证调用size方法时的一致性问题:1)判断所有的segment总修改次数是否大于上一次统计的总修改次数,如果大于,说明有修改,重新统计。
2)如果尝试次数超过阈值,则对每一个Segment加锁,再重新统计。
为了尽量不锁住所有Segment,首先乐观地假设Size过程中不会有修改。当尝试一定次数,才无奈转为悲观锁,锁住所有Segment保证强一致性。
HashMap,ConcurrentHashMap 原理分析
标签:nbsp 如何 entry 个数 超过 结构 次数 code put
原文地址:https://www.cnblogs.com/mcahkf/p/9023659.html