final int hash(Object k) {
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
// 下面进行的是一个hash的扰乱
// 因为在下面我们直接与 length-1 与操作
// 如果不进行扰动会导致高位的贡献为0
// 所以这里是将高位部分 (h>>>20) 和中间位 (h>>>12)
// 和低位都进行了一个计算最后得到我们的数值
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
// indexFor函数获取当前的Object插入的下标
// 由于 Java 中初始化和扩容hash存储的数组都是 2的幂次
// 所以直接用 & (2^n-1) 代替 % 2^n 的操作
// 还有一个好处就是,取模操作对负数的支持不好
// 直接与操作保证了不会出现负数,无需考虑数组越界
static int indexFor(int h, int length) {
return h & (length-1);
}
Java8
static final int hash(Object key) {
int h;
// 追求速率,直接一次高位与低位的异或混合,而不是四次
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
ConcurrentHashMap
Java7
private int hash(Object k) {
int h = hashSeed;
if ((0 != h) && (k instanceof String)) {
return sun.misc.Hashing.stringHash32((String) k);
}
h ^= k.hashCode();
// Spread bits to regularize both segment and index locations,
// using variant of single-word Wang/Jenkins hash.
h += (h << 15) ^ 0xffffcd7d;
h ^= (h >>> 10);
h += (h << 3);
h ^= (h >>> 6);
h += (h << 2) + (h << 14);
return h ^ (h >>> 16);
}
int j = (hash >>> segmentShift) & segmentMask;
Java8
Java 8 里面的求hash的方法从hash改为了spread。
static final int spread(int h) {
return (h ^ (h >>> 16)) & HASH_BITS;
}
HashTable (线程安全)
Java7
private int hash(Object k) {
// 简单进行hash,并取其hashCode
// hashSeed will be zero if alternative hashing is disabled.
return hashSeed ^ k.hashCode();
}
// 没有单独的 indexOf() 只有下面的:
// 和 0x7FFFFFFF 进行与操作是为了避免出现负数求模
int index = (hash & 0x7FFFFFFF) % tab.length;