盡信書不如無書,我今天在看網上的一些資料的時候發現一遍篇《HashMap和Hashtable的區別》的文章,隨手就在Eclipse里實驗了一下,結果發現很多原來文章中的錯誤,現在把這個問題修改好以后貼在這里,希望對大家的學習也有幫助。
HashMap
和Hashtable的區別。
錯誤說法:
<!--[if !supportLists]-->
1.
<!--[endif]-->
HashTable
不允許
null
值
(key
和
value
都不可以
),HashMap
允許
null
值
(key
和
value
都可以
)
。
這句話容易讓人誤會,到底是怎么個不允許法呢?其實在編譯期不會有任何的不一樣,會照樣執行,只是在運行期的時候 Hashtable 中設置的話回出現空指針異常
這句話容易讓人誤會,到底是怎么個不允許法呢?其實在編譯期不會有任何的不一樣,會照樣執行,只是在運行期的時候 Hashtable 中設置的話回出現空指針異常
<!--[if !supportLists]-->
2.
<!--[endif]-->
在
HashMap
中,
null
可以作為鍵,這樣的鍵只有一個;
可以有一個或多個鍵所對應的值為null
。當get()
方法返回null
值時,即可以表示 HashMap
中沒有該鍵,也可以表示該鍵所對應的值為null
。因此,在HashMap
中不能由get()
方法來判斷HashMap
中是否存在某個鍵,
而應該用containsKey()
方法來判斷。
不用多說,看下面的程序就可以:
HashMap map =
new
HashMap();
map.put(
"Null"
,
null
);
map.put(
null
,
"Null"
);
map.put(
null
,
"Empty"
);
System.
out
.println(map.get(
null
));
System.
out
.println(map.get(
"Null"
));
System.
out
.println(map.get(
"NullThere"
));
System.
out
.println(map.
containsKey
(
"Null"
));
System.
out
.println(map.
containsKey
(
"NullThere"
));
輸出結果為:
Empty
null
null
true
false
<!--[if !vml]-->
|
HashMap
|
Hashtable
|
繼承,實現
|
HashMap
<K,V>
extends
AbstractMap<K,V>
implements
Map<K,V>, Cloneable, Serializable
|
Hashtable
<K,V>
extends
Dictionary<K,V>
implements
Map<K,V>, Cloneable,Serializable
|
多線程,同步
|
未同步的,可以使用
Colletcions
進行同步
MapCollections.synchronizedMap(Mapm)
|
已經同步過的可以安全使用
|
對null的處理
|
HashMap map =
new
HashMap();
map.put(
null
,
"Null"
);
map.put(
"Null"
,
null
);
map.containsKey(
null
);
map.containsValue(
null
);
以上這
5
條語句無論在編譯期,還是在運行期都是沒有錯誤的
.
在HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,即可以表示 HashMap中沒有該鍵,也可以表示該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。
|
Hashtable table = new Hashtable();
table.put(null, "Null");
table.put("Null", null);
table.contains(null);
table.containsKey(null);
table.containsValue(null);
后面的
5
句話在編譯的時候不會有異常,可在運行的時候會報空指針異常
具體原因可以查看源代碼
public synchronized V put(K key, V value) {
// Make sure the value is not null
if (value == null) {
throw new NullPointerException();
}
………….
|
增長率
|
void
addEntry(
int
hash, K key, V value,
int
bucketIndex) {
Entry<K,V> e =
table
[bucketIndex];
table
[bucketIndex] =
new
Entry<K,V>(hash, key, value, e);
if
(
size
++ >=
threshold
)
resize
(2 *
table
.
length
);
}
|
protected
void
rehash() {
int
oldCapacity =
table
.
length
;
Entry[] oldMap =
table
;
int
newCapacity = oldCapacity * 2 + 1;
Entry[] newMap =
new
Entry[newCapacity];
modCount
++;
threshold
= (
int
)(newCapacity *
loadFactor
);
table
= newMap;
for
(
int
i = oldCapacity ; i-- > 0 ;) {
for
(Entry<K,V> old = oldMap[i] ; old !=
null
; ) {
Entry<K,V> e = old;
old = old.
next
;
int
index = (e.
hash
& 0x7FFFFFFF) % newCapacity;
e.
next
= newMap[index];
newMap[index] = e;
}
}
}
|
哈希值的使用
|
HashMap
重新計算
hash
值,而且用與代替求模
public
boolean
containsKey(Object key) {
Object k = maskNull(key);
int
hash = hash(k.hashCode());
int
i = indexFor(hash, table.length);
Entry e = table[i];
while
(e !=
null
) {
if
(e.hash == hash && eq(k, e.key))
return
true
;
e = e.next;
}
return
false
;
}
|
HashTable
直接使用對象的
hashCode
,代碼是這樣的:
public
synchronized
boolean
containsKey(Object key) {
Entry tab[] =
table
;
int
hash = key.
hashCode
();
int
index = (hash & 0x7FFFFFFF) % tab.
length
;
for
(Entry<K,V> e = tab[index] ; e !=
null
; e = e.
next
) {
if
((e.
hash
== hash) && e.
key
.equals(key)) {
return
true
;
}
}
return
false
;
}
|
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
