Hashtable和HashMap的区别

HashTable不允许空值

这个是Hashtableput方法源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
}

我简单查了一下校验的原因,可信度比较高的是因为Hashtable出现的比较早,是在Java 1.0引入的,发布于1996年1月,可能是为了确认get(key)方法返回null时,不是因为值为null而返回,而是因为真的没有这个key

HashMap是在Java 1.2引入的,发布于1998年12月。Hashmap继承于AbstractMap

Hashtable是线程安全的

Hashtable主要的方法都增加了synchronized关键字,确保了线程安全,HashMap则没有。

性能比HashMap差

也是因为增加synchronized关键字

继承差异

HashMap继承的是AbstractMap,而`Hash

遍历差异

HashMap引入了fail-fast机制,如果迭代过程中被其他线程做了修改(除迭代器的remove方法外),会抛出ConcurrentModificationException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final void forEach(Consumer<? super K> action) {  
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}

Hashtable因为用了同步机制,就不存在这个问题了

一些题外话

由于Hashtable几乎所有的方法都是同步的,所以实际开发中很少使用,而我自己则是从来没用过。需要多线程使用时,建议选择ConcurrentHashMap