前言
取余法是最常见的hash算法之一。HashMap和HashTable都是基于取余法来计算hashCode所对应的数组下标的,只是基于各自的特点做了一些特殊的处理,从而也导致了它们的初始值和扩容方法有所差异。
HashMap的初始值
HashMap的初始值是16,而且每次扩容 n * 2,对于我们传入的初始值,HashMap也要将其处理成最接近的2 ^ n才予以初始化。HashMap没有线程安全的处理,在设计理念上追求性能的极致。甚至连取余法这样一个步骤也得到了优化。
如果一个数 b = 2 ^ n,b - 1的二进制是0…0 …111这种形式。此时 a % b == a & (b -1),& 运算的速度当然是优于%的。HashMap就是采用了计算方式,因此HashMap的初始值才必须是2 ^ n。
HashTable的初始值
HashTable的初始值是11,扩容 2 * n + 1。HashTable是线程安全的,同步机制决定了它无法追求运行速度上的极致。在取余法的时候,使用位运算来提升效率已经意义不大了,更多的精力用在考虑解决hash冲突上。使用质数和奇数的取模运算,可以将Hash冲突的概率降低到最小。其证明过程如下:
给定两个正整数A和B,A和B拥有公约数x。证明 A % B是x的倍数
解:
(1)
∵ A、B有公约数x
∴ A = ax,B = bx,其中a、b均为正整数
(2)
设 A / B 的商为m,余数为n,则有
A % B = n
A /