深入理解HashMap

HashMap和HashTable的区别

HashMap的底层原理?

HashMap是一个存储Key-Value键值对的集合,每一个键值对也叫Entry,Key-Value是作为一个整体出现的,这些键值对分散的存储在一个数组中,这个数组就叫HashMap。对HashMap来说,最常用的方法是Put和Get。HashMap数组的每一个元素不只是一个Entry对象,也是一个链表的头结点。

1、Put的原理(根据Key值计算HashCode,根据HashCode得到Entry的插入位置index)

比如调用HashMap.put("apple",0)插入一个Key为Apple的元素,这时候要确定插入的位置index。

index=Hash("apple"),假设计算的index是2,结果如下:

但是HashMap的长度是有限的,当插入的Entry越来越多时,会发生index冲突的情况,例如下面:

这时候可以用链表解决,HashMap数组中每一个元素不仅仅是一个Entry对象,也是一个链表的头结点。每一个Entry对象通过Next指针指向它的下一个Entry节点,当新来的Entry映射到冲突数组位置时,只需要插入对应的链表即可。插入时采用“头插入”

HashMap的底层实现还是数组,数组中的每个元素是链表。

 

这里我们再来复习put的流程:当我们想一个HashMap中添加一对key-value时,系统首先会计算key的hash值,然后根据hash值确认在table中存储的位置。该位置没有元素,则直接插入。否则迭代该处元素链表并依此比较其key的hash值。如果两个hash值相等且key值相等(e.hash == hash && ((k = e.key) == key || key.equals(k))),则用新的Entry的value覆盖原来节点的value。如果两个hash值相等但key值不等 ,则将该节点插入该链表的链头。具体的实现过程见addEntry方法,

2、Get的原理(根据Key值得到index)

把输入的Key做一次Hash映射,得到对应的index,

index=Hash("apple")

由于刚才所说的Hash冲突,同一个位置可能匹配到多个Entry对象,这时候就要顺着链表的头结点,依次向下查找。第一次查找到的节点是Entry6.Entry6的Key是banana,不是要找的结果,第二次查找的节点是Entry1,Entry1对应的Key是Apple,是要找的结果。

 

你知道HashMap的get()方法的工作原理吗?

HashMap默认的长度是多少?为什么这样规定?

HashMap的初始长度为16,每次拓展或者手动初始化时,必须为2的幂。

初始长度选择16是为了服务于从Key到index的Hash算法,我们要得到一个尽量均匀分布的Hash函数,利用Key的HashCode做取模运算,(index=HashCode(Key)%Length),但是取模运算的效率很低,所以HashMap发明者采用位运算的方式(采用按位与运算实现取模),如何进行位运算,有如下的公式:

index=HashCode(Key)%(Length-1)

可以看出:Hash算法最终得到的结果,取决于HashCode的后几位。

这样做的好处是:当Length是16或者其他2 的幂,Length-1的每一位都是1,index的结果等于HashCode的后面几位,只要输入的HashCode是分布均匀的,Hash算法计算的index也是均匀的

对于HashMap的table而言,数据分布需要均匀(最好每项都只有一个元素,这样就可以直接找到),不能太紧也不能太松,太紧会导致查询速度慢,太松则浪费空间。使用index=HashCode(Key)%(Length-1)就是为了让table中的元素尽量均匀。

所以说当length = 2^n时,不同的hash值发生碰撞的概率比较小,这样就会使得数据在table数组中分布较均匀,查询速度也较快。

(如果Length-1=0011,则index某些值出现的几率大,某些值永远不可能出现)

高并发情况下,为什么HashMap会出现死锁?

得到

在Java8中,HashMap的结构有什么优化?

在java8中,如果hash相同的Key的数量大于8时,会用红黑树代替链表。

高并发下的HashMap

一些需要注意的点

  • HashMap有负载因子和极限容量,默认负载因子为0.75
  • 两个线程同时尝试扩容HashMap时,可能会将链表形成环形链表,所有的next都不为空,进入死循环。(HashMap是线程不安全的
  • 两个线程同时进行put时可能会造成一个线程数据缺失。

 

posted on 2018-09-11 20:52  Aaron12  阅读(262)  评论(0编辑  收藏  举报

导航