浅析HashMap的实现原理

时间:2022-04-02 12:40:06

本文参照https://www.cnblogs.com/chengxiao/p/6059914.html#commentform作者的文章,并分享一些自己的体会。

本文将主要回答以下两个问题:

1. 为什么table的容量必须是2的N次方?

2. 在重写equals方法时,为什么要重写hashcode方法?

3. 为什么hash冲突的时候,将新插入的元素至于链表头?


1. 为什么table的容量必须是2的N次方?

浅析HashMap的实现原理

  • length为2的整数次幂的话,h&(length-1)就相当于对length取模,这样便保证了散列的均匀,同时也提升了效率;
  • length为2的整数次幂的话,这样length-1的bit位都为1,这样便保证了h&(length-1)的每一位可能为0,也可能为1(这取决于h的值),即与后的结果可能为偶数,也可能为奇数,这样便可以保证散列的均匀性,而如果length不是2的N次方的话,很明显length-1必然存在某一个bit位是0的情形,length不是2的N次方的情况包括两种:1.length为偶数,例如length=6,则length-1=5(101),存在0bit位;2.length为奇数,例如length=7,kength-1=6(110),同样存在bit位是0的情况。这样h&(length-1)肯定存在bit位为0的情形(包括最后的bit位是0),即只能为偶数,这样任何hash值都只会被散列到数组的偶数下标位置上,这便浪费了近一半的空间,因此,length取2的整数次幂,是为了使不同hash值发生碰撞的概率较小,这样就能使元素在哈希表中均匀地散列。
  • key---->hashcode------>hash----->index,整体上这是一个多对一的映射,而key----->hash这个过程也是一个多对一的映射,因此hash---->index必须为一对一的映射,而只有在bit位都为1时才符合这种情况,这应该是其原因之一.

浅析HashMap的实现原理

如上图所示,只有在length-1全为1时,h---->index的映射才符合一对一。PS:本图引用于https://www.cnblogs.com/chengxiao/p/6059914.html#commentform

2. 在重写equals方法时,为什么要重写hashcode方法?

java的帮助文档要求,如果equal方法重写,那么hashcode也必须重写。其实际的目的在于,如果a.equals(b),那么必须保证其hashcode值相等。

浅析HashMap的实现原理

即keyA和keyb相等,经过hashcode映射后的值也必须相等。


3. 为什么hash冲突的时候,将新插入的元素至于链表头?

例如要插入的元素为A,链表中之前存有B和C两个元素,我们很容易定位到table[i],只需要使得A=table[i];A->next = B;即可,否则的话需要先遍历链表,然后在末尾进行插入,这样增加了遍历的开销。


开通博客第一天,good luck!