一、线程的安全性
  Hashtable是线程安全的,HashMap不是线程安全的。为什么前者是线程安全的呢?我们这时就要看看Hashtable的源码了:

  public synchronized Map put(K key,V value);
  public synchronized Map get(Object key);

  由以上代码就可以看出,Hashtable使用sychronized修饰的,意味着一次只能有一个线程去修改Hashtable。换句话说,只有等到HashMap的同步锁才能对它进行操作,等到锁释放了,下一个得到锁的线程才能去修改HashMap。

二、性能的优劣性

  从第一条的区别我们可以得知,由于同步锁的缘故,Hashtable是线程安全的,但这也使得其阻塞了其他的线程,在不做修改,只做查询的情况下,Hashtable的的效率会低于HashMap。但如果是要线程安全同时又要保证效率的话,建议使用Hashtable。

三、关于NULL

  Hashtable是不允许键或者值为null,而恰恰相反,HashMap允许键和值都为null。是什么导致上述的情况呢?那么就让我们看一看Hashtable put 和HashMap hash的方法逻辑。

Hashtable put:

public synchronized Hashtable put(K key,V value){
if(value==null){
throw new NullPointerException();
}
Entry tab[ ] = table;
int hash = key.hashCode();
.......
}

HashMap hash:

static final int hash(Object key){
int h;
return ( key == null ) ? 0 : ( h = key.hashCode ( ) ) ^ ( h >> 16 );

}

由上述的代码可以看出,Hashtable key为null时,会直接抛出空指针异常,而HashMap对null做了特殊的处理。

四、实现的方式

Hashtable的继承的源码:

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable

HashMap的继承源码:

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable

  由上述代码可以看出,两者继承的类是不一样的,Hashtable继承了Dictionary类,而HashMap继承的是AbstractMap类

五、容量扩容
  HashMap的初始容量为:16,Hashtable初始容量为11,两者的默认加载因子都是:0.75f。
 当现有容量大于总容量 * 负载因子时,HashMap扩容规则为当前容量的的2倍,Hashtable扩容规则为当前容量的2倍 +1。

六、迭代器
  HashMap中Iterator迭代器是fail-fast的,而Hashtable的迭代器不是fail-fast的。所以,在其他线程改变HashMap的结构,将会抛出ConcurrentModificationException异常,而Hashtable则不会。但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。