HashMap:
(1)HashMap不是线程安全的,在多线程操作中,需要使用synchronized关键字。
(2)HashMap是允许key和value为null的,key为null的hash值为0
Hashtable
(1)Hashtalbe所有的方法都是线程安全的,在每个公共方法上都有synchronized关键字。
(2)Hashtable不允许key和value为空
下面我从源码来看看
首先我们需要知道的是,HashMap和Hashtable的结构都是数组+链表的形式。
具体可以看看图解HashMap文章。
首先来看看HashMap的put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
这里就不看put的具体操作了,来看看hash(key)操作,它对应的值就是hash值。另外可以看到这些方法没有使用synchronized来进行同步,所以它不是线程安全的,这也说明了第一点。
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
可以看到,如果key为null的话,对应的hash值为0,这里也就是说明了HashMap是允许key为null的。
再来看看Hashtable的put方法
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;
}
从上面可以看到,方法上使用了synchronized关键字,说明Hashtable是同步的,它是线程安全的,另外从上面可以看到如果value为null,则就会抛出一个NullPointerException异常,如果key是一个null的话,在调用key.hashCode()的时候也会抛出一个空指针异常。所以Hashtable的key和value都是不允许为null的。