第一、继承不同
第一个不同主要是历史原因。Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现,继承自AbstractMap(This class provides a skeletal implementation of the Map)。
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable {...}
public class Hashtable<K, V> extends Dictionary<K, V> implements Map<K, V>, Cloneable, Serializable {...}
第二、线程安全不一样
Hashtable 中的方法是同步的,而HashMap中的方法在默认情况下是非同步的。
The HashMap class is roughly equivalent to(相当于) Hashtable, except that it is * unsynchronized and permits nulls.
写点题外话:StringBuilder是线程不安全,StringBuffer是线程安全。StringBuilder中的append方法没有使用synchronized关键字,意味着多个线程可以同时访问这个方法。在单线程中字符串的频繁拼接使用StringBuilder效率更高,对于多线程使用StringBuffer则更安全。感觉这种思想,和hashmap与hashtable的关系有异曲同工之妙。
第三、允不允许null值
Hashtable中,key和value都不允许出现null值,否则会抛出NullPointerException异常。
而在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
第四、遍历方式的内部实现上不同
Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。
第五、哈希值的使用不同
HashTable直接使用对象的hashCode。而HashMap重新计算hash值。
HashTable:
public int hashCode() {
return hash ^ Objects.hashCode(value);
}
HashMap:
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
第六、内部实现方式的数组的初始大小和扩容的方式不一样
HashTable中的hash数组初始大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
hashmap | 线程不安全 | 允许有null的键和值 | 效率高一点 | 方法不是Synchronize的,要提供外同步 | HashMap 继承于AbstractMap类 | HashMap是Hashtable的轻量级实现 |
hashtable | 线程安全 | 不允许有null的键和值 | 效率稍低 | 方法是Synchronize的 | Hashtable 继承于Dictionary 类 | Hashtable 比HashMap 要旧 |