@@ -68,6 +68,24 @@ public class Hashtable<K,V>
68
68
// 将“子Map”的全部元素都添加到Hashtable中
69
69
putAll(t);
70
70
}
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
+ }
71
89
72
90
public synchronized int size() {
73
91
return count;
@@ -131,7 +149,7 @@ public class Hashtable<K,V>
131
149
// 返回key对应的value,没有的话返回null
132
150
public synchronized V get(Object key) {
133
151
Entry tab[] = table;
134
- int hash = key.hashCode();
152
+ int hash = hash(key);
135
153
// 计算索引值,
136
154
int index = (hash & 0x7FFFFFFF) % tab.length;
137
155
// 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
@@ -179,7 +197,7 @@ public class Hashtable<K,V>
179
197
// 若“Hashtable中已存在键为key的键值对”,
180
198
// 则用“新的value”替换“旧的value”
181
199
Entry tab[] = table;
182
- int hash = key.hashCode();
200
+ int hash = hash(key);
183
201
int index = (hash & 0x7FFFFFFF) % tab.length;
184
202
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
185
203
if ((e.hash == hash) && e.key.equals(key)) {
@@ -211,7 +229,7 @@ public class Hashtable<K,V>
211
229
// 删除Hashtable中键为key的元素
212
230
public synchronized V remove(Object key) {
213
231
Entry tab[] = table;
214
- int hash = key.hashCode();
232
+ int hash = hash(key);
215
233
int index = (hash & 0x7FFFFFFF) % tab.length;
216
234
217
235
//从table[index]链表中找出要删除的节点,并删除该节点。
@@ -376,7 +394,7 @@ public class Hashtable<K,V>
376
394
Map.Entry entry = (Map.Entry)o;
377
395
Object key = entry.getKey();
378
396
Entry[] tab = table;
379
- int hash = key.hashCode();
397
+ int hash = hash(key);
380
398
int index = (hash & 0x7FFFFFFF) % tab.length;
381
399
382
400
for (Entry e = tab[index]; e != null; e = e.next)
@@ -394,7 +412,7 @@ public class Hashtable<K,V>
394
412
Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
395
413
K key = entry.getKey();
396
414
Entry[] tab = table;
397
- int hash = key.hashCode();
415
+ int hash = hash(key);
398
416
int index = (hash & 0x7FFFFFFF) % tab.length;
399
417
400
418
for (Entry<K,V> e = tab[index], prev = null; e != null;
@@ -837,7 +855,7 @@ public class Hashtable<K,V>
837
855
public synchronized boolean containsKey(Object key) {
838
856
Entry tab[] = table;
839
857
/计算hash值,直接用key的hashCode代替
840
- int hash = key.hashCode();
858
+ int hash = hash(key);
841
859
// 计算在数组中的索引值
842
860
int index = (hash & 0x7FFFFFFF) % tab.length;
843
861
// 找到“key对应的Entry(链表)”,然后在链表中找出“哈希值”和“键值”与key都相等的元素
@@ -852,4 +870,4 @@ public class Hashtable<K,V>
852
870
853
871
很明显,如果value为null,会直接抛出NullPointerException异常,但源码中并没有对key是否为null判断,有点小不解!不过NullPointerException属于RuntimeException异常,是可以由JVM自动抛出的,也许对key的值在JVM中有所限制吧。
854
872
4 . 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