总结:
-
继承的父类不同:HashTable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口
-
线程安全性:HashMap是非线程安全的,而HashTable是线程安全的,通过源码分析我们知道HashTable的每个方法都是实现了synchronized
-
key和value是否允许null值:HashMap可以存储key=null的键值对,HashTable不能存储key=null的键值对
-
hash值不同:HashTable直接使用对象的hashCode。而HashMap重新计算hash值
-
默认初始容量及如何扩容不同:HashMap的默认初始容量是16,HashTable默认初始容量是11;HashMap和HashTable的加载因子都是0.75;HashMap扩容:2N,而HashTable扩容:2N+1.
源码分析
1. 继承的父类不同
HashMap

HashTable
2. 线程安全性
HashMap的PUT方法
HashTable的PUT方法
如此我们可以看出,HashMap是线程不安全的,因此他们之间的区别有线程安全性不同。
3. key和value是否允许null值
HashMap的containsValue方法源码
HashTable的containsValue方法源码
通过上面的ContainsKey方法和ContainsValue的源码我们可以很明显的看出:
- Hashtable中,key和value都不允许出现null值。但是如果在Hashtable中有类似put(null,null)的操作,编译同样可以通过,因为key和value都是Object类型,但运行时会抛出NullPointerException异常,这是JDK的规范规定的;
- HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。
4. hash值不同
哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值
hashCode是jdk根据对象的地址或者字符串或者数字算出来的int类型的数值
HashMap
put方法
hash方法
HashTable
Hashtable计算hash值,直接用key的hashCode(),而HashMap重新计算了key的hash值,Hashtable在求hash值对应的位置索引时,用取模运算,而HashMap在求位置索引时,则用与运算,且这里一般先用hash&0x7FFFFFFF后,再对length取模,&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号外改变,而后面的位都不变。
5. 默认初始容量及如何扩容不同
HashTable