1.继承关系
Hashtable 继承自 Dictiionary
HashMap 继承自AbstractMap
2.线程安全性
其中 Hashtable put等大部分方法 都加了synchronized关键字是同步的
不允许value==null&&调用了key的hashCode方法,如果key==null,会抛出空指针异常。
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
;
}
HashMap put方法等所有方法都没有synchronized关键字是非同步的
允许key==null&&并没有对value进行任何调用,所以允许value为null。
public
V put(K
key
, V
value
) {
if
(
table
==
EMPTY_TABLE
) {
inflateTable(
threshold
);
}
if
(
key
==
null
)
return
putForNullKey
(
value
);
int
hash
= hash(
key
);
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
;
}
其中:
HashTable中的contains是对value的检查
HashMap中的contains是对key的检查
实现原理:
HashMap和HashTable都使用哈希表来存储 。在数据结构上基本相同。(以下为1.7版本。1.8中不同)
HashMap解析(jdk1.8)
/**
* The hash table data. HashTable
*/
private
transient
Entry<K,V>[]
table
;
/**
//HashMap
transient
Entry<K,V>[]
table
= (Entry<K,V>[])
EMPTY_TABLE
;
//Entry
protected Entry(int hash, K key, V value, Entry<K,V> next) {
this
.
hash
=
hash
;
this
.
key
=
key
;
this
.
value
=
value
;
this
.
next
=
next
;
}
HashMap/HashTable内部用Entry数组实现哈希表,hash值相同(映射到同一个桶)的值放到同一个entry数组。