# `HashMap`和`Hashtable`之间的区别

> 原文： [https://beginnersbook.com/2014/06/difference-between-hashmap-and-hashtable/](https://beginnersbook.com/2014/06/difference-between-hashmap-and-hashtable/)

`HashMap`和`Hashtable`有什么区别？这是 Java / J2EE 专业人员常见的[面试问题](https://beginnersbook.com/2013/05/java-interview-questions/)之一。`HashMap`和`Hashtable`这两个类实现了`java.util.Map`接口，但它们的工作方式和用法存在差异。在这里，我们将讨论这些类之间的差异。

## `HashMap` vs `Hashtable`

1） [`HashMap`](https://beginnersbook.com/2013/12/hashmap-in-java-with-example/)是非同步的。这意味着如果它在多线程环境中使用，那么多个线程可以同时访问和处理`HashMap`。

[`Hashtable`](https://docs.oracle.com/javase/6/docs/api/java/util/Hashtable.html)已同步。它确保在给定时刻不超过一个线程可以访问`Hashtable`。在`Hashtable`上工作的线程获取一个锁，使其他线程等待，直到它的工作完成。

2）`HashMap`允许一个空键和任意数量的空值。

`Hashtable`不允许使用`null`键和`null`值。

3）`HashMap`实现[`LinkedHashMap`](https://beginnersbook.com/2013/12/linkedhashmap-in-java/) 维护插入顺序， [`TreeMap`](https://beginnersbook.com/2013/12/treemap-in-java-with-example/) 根据键的升序对映射进行排序。

`Hashtable`不保证任何顺序。它不以任何特定顺序维护映射。

4）最初`Hashtable`不是[集合框架](https://beginnersbook.com/java-collections-tutorials/)的一部分，它在被改进以实现`Map`接口之后成为了一个集合框架成员。

`HashMap`实现了`Map`接口，从一开始就是集合框架的一部分。

5）这些类之间的另一个区别是`HashMap`的迭代器是一个快速失败并抛出[`ConcurrentModificationException`](https://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html)如果任何其他`Thread`通过添加或删除除迭代器自己的`remove()`方法之外的任何元素在结构上修改映射。简单来说，快速失败意味着：当调用`iterator.next()`时，如果在创建迭代器和调用`next()`的那一刻之间进行了任何修改，则立即抛出`ConcurrentModificationException`。

`Hashtable`的枚举器不是快速失败的。

对于例如

`HashMap`：

```java
HashMap hm= new HashMap();
....
....
Set keys = hm.keySet();
for (Object key : keys) {
    //it will throw the ConcurrentModificationException here
    hm.put(object & value pair here); 
}
```

**Hashtable：**

```java
Hashtable ht= new Hashtable();
....
.....
Enumeration keys = ht.keys();
 for (Enumeration en = ht.elements() ; en.hasMoreElements() ; en.nextElement()) {
      //No exception would be thrown here
      ht.put(key & value pair here); 
 }
```

## 何时使用`HashMap`和`Hashtable`？

1）如上所述，`HashMap`与`Hashtable`是同步。如果需要线程安全操作，那么可以使用`Hashtable`，因为它的所有方法都是同步的，但它应该是遗留类，应该避免，因为它没有任何关于它，`HashMap`无法完成。对于[多线程](https://beginnersbook.com/2013/03/multithreading-in-java/)环境，我建议你使用`ConcurrentHashMap`（几乎类似于 Hashtable），甚至可以使`HashMap`显式同步（[在这里阅读](https://beginnersbook.com/2013/12/how-to-synchronize-hashmap-in-java-with-example/)）。

2）同步操作性能较差，因此除非需要，否则应避免使用。因此，对于非线程环境，应该毫无疑问地使用`HashMap`。