微笑的撸代码

记录平常遇到的问题以及解决方法

什么是HashMap?

1、HashMap的底层原理

     HashMap是存储Key-Value键值对的集合,每个键值对也叫做Entry,这些Entry分散存储在一个数组中,这个数组可以成称是HashMap的主干。

      HashMap中的每一个元素的初始值都是NULL,且默认数组长度是16

          

    HashMap有两个方法:GETPUT


2、PUT方法的原理

    以 hashMap.put('apple',7)这个操作为例。那它在底层都干了些什么呢?

     首先在底层会用哈希函数index = Hash('apple') 来确定apple这个key(键)应该插入HashMap中的哪个位置, 假定index最后的值为2,那么结果如下图所示:

        

    apple-7这个键值对就这样插入到了HashMap中,看到这里不知道小伙伴有没有这样一个疑问,HashMap的默认是16,要是根据哈希函数算出来的index要是一样,那岂不是和上一个冲突了?就像下面出现的情况:

      

   对,再完美的哈希函数在有限的长度下也难免会有index冲突的情况出现,那该怎么解决呢?


   我们可以用链表来解决!!!


   其实HashMap中的每一个元素不仅仅是一个Entry,还是一个链表的头节点,每一个Entry可以通过Next来指向下一个Entry节点,所以当有index发生冲突时,只需插入到相应的链表中即可。如下图:

    

  需要注意的是,这里插入到链表中采用的是“头插法”,那为什么不插入到上一个Entry的后面呢,下面HashMapGET方法有讲到,请继续往下看哦~~


3、GET方法的原理

        同样的以HashMap.get('apple')为例,根据哈希函数得到index位置去获取相应的值,由于刚才所说的Hash冲突,同一个位置有可能匹配到多个Entry,这时候就需要顺着对应链表的头节点,一个一个向下来查找。假设我们要查找的Key是“apple”:

        

    第一步,我们查看的是头节点Entry6,Entry6的Key是banana,显然不是我们要找的结果。

    第二步,我们查看的是Next节点Entry1,Entry1的Key是apple,正是我们要找的结果。

    之所以把Entry6放在头节点,是因为HashMap的发明者认为,后插入的Entry被查找的可能性更大。这就是为什么要新的Entry要以“头插法”插入链表的原因。

    看到这里想必大家对HashMap有一定的了解了吧,想不想对HashMap的了解更深入一点? Let's   go!!!


    前面有说到HashMap的默认长度是16,那为什么是16,难道10不行吗?下面为大家解答为什么HashMap默认长度是16的原因:

   其实HashMap的长度主要是服务于key映射到index的Hash算法,如何实现一个尽量均匀分布的Hash函数呢?我们通过利用Key的HashCode值来做某种运算。为了实现高效的Hash算法,HashMap的发明者使用了位运算的方法。

如何进行位运算呢?有如下的公式(Length是HashMap的长度):

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

下面我们以值为“book”的Key来演示整个过程:


1.计算book的hashcode,结果为十进制的3029737,二进制的101110001110101110 1001。


2.假定HashMap长度是默认的16,计算Length-1的结果为十进制的15,二进制的1111。


3.把以上两个结果做与运算101110001110101110 1001 & 1111 = 1001,十进制是9,所以 index=9。


可以说,Hash算法最终得到的index结果,完全取决于Key的Hashcode值的最后几位。


那默认长度是10的呢?

假设HashMap的长度是10,重复刚才的运算步骤:


单独看这个结果,表面上并没有问题。我们再来尝试一个新的HashCode  101110001110101110 1011


让我们再换一个HashCode 101110001110101110 1111 试试  :


是的,虽然HashCode的倒数第二第三位从0变成了1,但是运算的结果都是1001。也就是说,当HashMap长度为10的时候,有些index结果的出现几率会更大,而有些index结果永远不会出现(比如0111)!

这样,显然不符合Hash算法均匀分布的原则。

反观长度16或者其他2的幂,Length-1的值是所有二进制位全为1,这种情况下,index的结果等同于HashCode后几位的值。只要输入的HashCode本身分布均匀,Hash算法的结果就是均匀的。


阅读更多
个人分类: Java
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

什么是HashMap?

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭