上一篇讲了String、Integer复写了Object中的hashCode方法,而对于HashMap或类对象来说是直接使用了Object中的hashCode方法。正文如下:
public class Test {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("key", "value");
Hashtable table = new Hashtable();
table.put("key", "value");
Test test = new Test();
test.hashCode();
}
}
对于HashMap中 key值的hash计算源码如下:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
可以看到 HashMap 中的key值可以为null,key值的hash值的计算方法为:key的hash值高16位不变,低16位与高16位异或作为key最终的hash值。(h>>>16,表示无符号右移16位,高位补0)
对于Hashtable中的key值计算的hash源码如下:
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for(; entry != null ; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
entry.value = value;
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
可以看到Hashtable线程安全是因为添加了 synchronized 关键字,同时 Hashtable key值是不可以为空的。
其中 int index = (hash & 0x7FFFFFFF) % tab.length;
为了在hash为负值的情况下,去掉起符号位,所以和0x7FFFFFFF进行&操作。0x7FFFFFFF 二进制 0111 1111 1111 1111 1111 1111 1111 1111,负数与其进行&操作将产生一个正整数。
参考及扩展阅读:
https://www.cnblogs.com/liujinhong/p/6576543.html
hashcode的解析 https://www.jianshu.com/p/2c1b6dd312eb