HashTable不允许空值
这个是Hashtable
的put
方法源码:
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) { if (value == null) { throw new NullPointerException(); } 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