Java的Object類中有一個hashCode()方法:java
public final native Class<?> getClass(); public native int hashCode(); public boolean equals(Object obj) { return (this == obj); } public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
indexFor()源碼以下:數組
static int indexFor(int h, int length) { return h & (length-1); }
由於hashMap要求Entry數組長度必須爲2的冪(hashMap默認值爲16,hashTable沒有這個要求,默認值爲11),因此上述代碼就是取h的低4位做爲Entry數組的下標。由於覆蓋equals()須要覆蓋hashCode(),因此hashCode()有時並不十分完美,好比只和高位有關等等,所以須要再次hash()一下。app
hash()方法在JDK1.7中以下:this
static int hash(int h) { // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
這樣設計保證了對象的hashCode的32位值只要有一位發生改變,整個hash()返回值就會改變,高位的變化會反應到低位裏。設計
具體分析參考:http://www.iteye.com/topic/709945code
https://www.zhihu.com/question/20733617對象
hash()方法在JDK1.8中以下:blog
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
這樣設計保證了對象的hashCode的高16位的變化能反應到低16位中,相比較而言減小了過多的位運算,是一種折中的設計。ip