## HashMap的hash算法

 hash源码如下

JDK HashMap几个有意思的问题_数组

 做了什么?

  • 获取hash值
  • hash值无符号右移
  • 然后把前两步的结果做亦或运算

  为啥这么做?

  • 经过上边的操作,右移 和 亦或运算。得到的hash值二进制的高十六位和低十六位将都保留hash值的数字特征。
  • 另外,也和hash寻址有关,按照正常的逻辑,我们想要把hash值对数组长度取模,然后当做数字下标。而源码进行了优化,通过 (n-1)& hash 值得到下标,其实一样的效果,这不过这样的效果更好一点 。
  • 再根据上边的hash寻址,位移,和亦或,可以减少hash冲突。

## Hash碰撞怎么做(hash冲突)

  链表+红黑树

  如果元素的key的hash值相同,则使用一个链表来存放。链表查找一个元素的时间复杂度为 O(n),链表到达一定长度(8),则使用红黑树,红黑树寻找一个元素的时间的时间复杂度为O(logn)

 

## rehash 扩容 

 当存放的长度到达阈值以后,就要出发rehash,将原来的进行重新hash,判断hash值和新的数组长度与的结果,是否多了一个比特,如果没多则还是原来的位置,如果多了,则是原来的位置 + 原来的数组的长度,就是在新数组的下标位置。