HashMap实现原理:容量、负载因子、hash与定位都搞定了吗?( 五 )

在设计hash函数时 , 因为目前的table长度n为2的次幂 , 所以计算下标的时候 , 可使用按位与&代替取模%:

(n - 1) & hash

设计者认为这方法很容易发生碰撞 。 为什么这么说呢?不妨思考一下 , 在n - 1为15(0x1111)时 , 散列真正生效的只是低4bit的有效位 , 当然容易碰撞了 。

因此 , 设计者想了一个顾全大局的方法(综合考虑了速度、作用、质量) , 就是把高16bit和低16bit异或了一下 。 设计者还解释到因为现在大多数的hashCode的分布已经很不错了 , 就算是发生了碰撞也用O(logn)的tree去做了 。 仅仅异或一下 , 既减少了系统的开销 , 也不会造成因为高位没有参与下标的计算(table长度比较小)时 , 引起的碰撞 。

好吧 , 我还是不理解为什么“很”容易发生碰撞 。 难道hash的分布不是均匀的吗?

碰撞

调用put方法时 , 尽管我们设法避免碰撞以提高HashMap的性能 , 还是可能发生碰撞 。 据说碰撞率还挺高 , 平均加载率到10%时就会开始碰撞 。 我们使用拉链法来处理碰撞节点 。

推荐阅读