@@ -68,6 +68,24 @@ public class Hashtable<K,V>
6868 // 将“子Map”的全部元素都添加到Hashtable中
6969 putAll(t);
7070 }
71+
72+ private int hash(Object k) {
73+ if (useAltHashing) {
74+ if (k.getClass() == String.class) {
75+ return sun.misc.Hashing.stringHash32((String) k);
76+ } else {
77+ int h = hashSeed ^ k.hashCode();
78+
79+ // This function ensures that hashCodes that differ only by
80+ // constant multiples at each bit position have a bounded
81+ // number of collisions (approximately 8 at default load factor).
82+ h ^= (h >>> 20) ^ (h >>> 12);
83+ return h ^ (h >>> 7) ^ (h >>> 4);
84+ }
85+ } else {
86+ return k.hashCode();
87+ }
88+ }
7189
7290 public synchronized int size() {
7391 return count;
@@ -131,7 +149,7 @@ public class Hashtable<K,V>
131149 // 返回key对应的value,没有的话返回null
132150 public synchronized V get(Object key) {
133151 Entry tab[] = table;
134- int hash = key.hashCode();
152+ int hash = hash(key);
135153 // 计算索引值,
136154 int index = (hash & 0x7FFFFFFF) % tab.length;
137155 // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
@@ -179,7 +197,7 @@ public class Hashtable<K,V>
179197 // 若“Hashtable中已存在键为key的键值对”,
180198 // 则用“新的value”替换“旧的value”
181199 Entry tab[] = table;
182- int hash = key.hashCode();
200+ int hash = hash(key);
183201 int index = (hash & 0x7FFFFFFF) % tab.length;
184202 for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
185203 if ((e.hash == hash) && e.key.equals(key)) {
@@ -211,7 +229,7 @@ public class Hashtable<K,V>
211229 // 删除Hashtable中键为key的元素
212230 public synchronized V remove(Object key) {
213231 Entry tab[] = table;
214- int hash = key.hashCode();
232+ int hash = hash(key);
215233 int index = (hash & 0x7FFFFFFF) % tab.length;
216234
217235 //从table[index]链表中找出要删除的节点,并删除该节点。
@@ -376,7 +394,7 @@ public class Hashtable<K,V>
376394 Map.Entry entry = (Map.Entry)o;
377395 Object key = entry.getKey();
378396 Entry[] tab = table;
379- int hash = key.hashCode();
397+ int hash = hash(key);
380398 int index = (hash & 0x7FFFFFFF) % tab.length;
381399
382400 for (Entry e = tab[index]; e != null; e = e.next)
@@ -394,7 +412,7 @@ public class Hashtable<K,V>
394412 Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
395413 K key = entry.getKey();
396414 Entry[] tab = table;
397- int hash = key.hashCode();
415+ int hash = hash(key);
398416 int index = (hash & 0x7FFFFFFF) % tab.length;
399417
400418 for (Entry<K,V> e = tab[index], prev = null; e != null;
@@ -837,7 +855,7 @@ public class Hashtable<K,V>
837855 public synchronized boolean containsKey(Object key) {
838856 Entry tab[] = table;
839857/计算hash值,直接用key的hashCode代替
840- int hash = key.hashCode();
858+ int hash = hash(key);
841859 // 计算在数组中的索引值
842860 int index = (hash & 0x7FFFFFFF) % tab.length;
843861 // 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
@@ -852,4 +870,4 @@ public class Hashtable<K,V>
852870
853871 很明显,如果value为null,会直接抛出NullPointerException异常,但源码中并没有对key是否为null判断,有点小不解!不过NullPointerException属于RuntimeException异常,是可以由JVM自动抛出的,也许对key的值在JVM中有所限制吧。
8548724 . Hashtable扩容时,将容量变为原来的2倍加1,而HashMap扩容时,将容量变为原来的2倍。
855- 5 . Hashtable计算hash值,直接用key的hashCode(),而HashMap重新计算了key的hash值 ,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。
873+ 5 . Hashtable和HashMap都重新计算了key的hash值 ,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。
0 commit comments