JDK1.8中,对HashMap的hash算法和寻址算法有何优化?
HashMap源码
1. hash(Object key)算法
Computes key.hashCode() and spreads (XORs) higher bits of hash to lower. Because the table uses power-of-two masking, sets of hashes that vary only in bits above the current mask will always collide. (Among known examples are sets of Float keys holding consecutive whole numbers in small tables.) So we apply a transform that spreads the impact of higher bits downward. There is a tradeoff between speed, utility, and quality of bit-spreading. Because many common sets of hashes are already reasonably distributed (so don't benefit from spreading), and because we use trees to handle large sets of collisions in bins, we just XOR some shifted bits in the cheapest possible way to reduce systematic lossage, as well as to incorporate impact of the highest bits that would otherwise never be used in index calculations because of table bounds.
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
h = key.hashCode() 表示 h 是 key 对象的 hashCode 返回值;
h >>> 16 是 h 右移 16 位,因为 int 是 4 字节,32 位,所以右移 16 位后变成:左边 16 个 0 + 右边原 h 的高 16 位;最后把这两个进行异或返回。
异或:二进制位运算。如果一样返回 0,不一样则返回 1。 例:两个二进制 110 和 100 进行异或 110 ^ 100 结果= 010
hash算法的优化:对每个hash值,在它的低16位中,让高低16位进行异或,让它的低16位同时保持了高低16位的特征,尽量避免一些hash值后续出现冲突,大家可能会进入数组的同一位置。
2.putVal() 中寻址部分
(p = tab[i = (n - 1) & hash]) == null
tab 就是 HashMap 里的 table 数组 Node<K,V>[] table ;
n 是这个数组的长度 length;
hash 就是上面 hash() 方法返回的值;
寻址算法的优化:用与运算替代取模,提升性能。(由于计算机对比取模,与运算会更快)