一、继承不同,HashTable 继承Dictionary;HashMap继承AbstractMap
二、HashTable线程安全,HashMap 线程不安全。HashTable的操作方法是Synchronize的,而HashMap内部是一个Entry数组,当发生 hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结 点加入。HashTable在并发环境下不需要额外做同步处理,但由于并发环境下会锁整个table,因此也造成了效率低下,因此 ConcurrentHashMap 出来了,采用分段锁,效率得到提升。而HashMap在并发环境下需要做额外的同步处理。
例如:HashMap的put
1 public V put(K key, V value) { 2 return putVal(hash(key), key, value, false, true); 3 }
HashTable的put
1 public synchronized V put(K key, V value) { 2 // Make sure the value is not null 3 if (value == null) { 4 throw new NullPointerException(); 5 } 6 7 // Makes sure the key is not already in the hashtable. 8 Entry<?,?> tab[] = table; 9 int hash = key.hashCode(); 10 int index = (hash & 0x7FFFFFFF) % tab.length; 11 @SuppressWarnings("unchecked") 12 Entry<K,V> entry = (Entry<K,V>)tab[index]; 13 for(; entry != null ; entry = entry.next) { 14 if ((entry.hash == hash) && entry.key.equals(key)) { 15 V old = entry.value; 16 entry.value = value; 17 return old; 18 } 19 } 20 21 addEntry(hash, key, value, index); 22 return null; 23 }
三、Contains 方法不同
HashMap 包含containsValue和containsKey不包含contains,而HashTable都包含。
四、是否允许Null值
HashTable key和value都不允许为空
1 public synchronized V put(K key, V value) { 2 // Make sure the value is not null 3 if (value == null) { 4 throw new NullPointerException(); 5 }
五、计算hash值方式不同
HashMap的hash值计算为:
1 static final int hash(Object key) { 2 int h; 3 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 4 }
而HashTable直接通过hashCode获得hash值:
1 int hash = key.hashCode();
六、计算索引位置不一样:
HashMap计算索引位置:
index = (n - 1) & hash
HashTable计算索引位置:
int index = (hash & 0x7FFFFFFF) % tab.length
七、解决Hash冲突的方式不一样
HashMap 在冲突频率较高时,有一个链表转红黑树的过程以提高查找效率,而HashTable始终以链表方式存储。