1. 概述

这篇短文将聚焦在 Java 中 HashMapHashtable 的核心差异上。

2. Java 中的 Hashtable 与 HashMap

HashtableHashMap 非常相似 —— 它们都实现了 Map 接口,用于存储键值对。

✅ 常见操作如 put()get()remove()containsKey() 的时间复杂度都是 O(1),内部通过哈希表和桶结构实现。

❌ 但两者都不保证插入顺序,也就是说第一个插入的元素未必是第一个被遍历到的。

虽然看起来差不多,但在某些场景下,它们的表现却截然不同。下面我们就来逐个分析这些差异。

3. Hashtable 与 HashMap 的主要区别

3.1. 线程安全性

⚠️ Hashtable 是线程安全的,可以被多个线程共享访问。

HashMap 不是线程安全的,如果要在多线程环境下使用,需要额外加锁或者使用 Collections.synchronizedMap() 进行包装。

当然你也可以自己写同步逻辑,比如加个 synchronized 块或用 ReentrantLock

✅ 总的来说,在单线程环境下,HashMap 更快、内存占用更少;因为没有同步开销。

3.2. 对 null 的处理

  • HashMap 允许一个 key 为 null,也允许多个 value 为 null
  • Hashtable 不允许 key 或 value 为 null,否则会抛出 NullPointerException

示例代码:

HashMap<String, String> map = new HashMap<String, String>();
map.put(null, "value");
map.put("key1", null);
map.put("key2", null);

结果是:

assertEquals(3, map.size());

再看 Hashtable:

Hashtable<String, String> table = new Hashtable<String, String>();
table.put("key", null); // 抛出 NullPointerException

甚至 key 为 null 也会报错:

table.put(null, "value"); // 同样抛出 NullPointerException

所以使用 Hashtable 时要特别注意避免 null 值,不然容易踩坑。

3.3. 遍历方式

  • HashMap 使用的是 Iterator(迭代器)
  • Hashtable 使用的是 Enumeration(枚举)

💡 IteratorEnumeration 的改进版,支持 remove() 方法,并且具备 fail-fast 特性。

⚠️ 如果在迭代过程中修改了集合结构(比如添加/删除元素),会抛出 ConcurrentModificationException 异常。

举个例子:

HashMap<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");

Iterator<String> iterator = map.keySet().iterator();
while(iterator.hasNext()){ 
    iterator.next();
    map.put("key4", "value4"); // 抛出 ConcurrentModificationException
}

这里因为在迭代中调用了 put(),导致结构变化,触发了 fail-fast 机制。

4. 什么时候选择 HashMap 而不是 Hashtable?

✅ 在单线程应用或不需要线程安全的场景下,优先选择 HashMap

⚠️ 自 JDK 1.8 起,官方已经不推荐使用 Hashtable,取而代之的是 ConcurrentHashMap

📌 如果你需要在并发环境中使用 Map,建议直接上 ConcurrentHashMap,性能更好、设计更现代。

5. 小结

这篇文章总结了 HashMapHashtable 的几个关键差异点:

特性 HashMap Hashtable
线程安全 ❌ 否 ✅ 是
null 支持 ✅ key/value 可以为 null ❌ 不允许 null
遍历方式 Iterator (fail-fast) Enumeration
性能 更快 较慢(因同步)
推荐使用场景 单线程或手动同步 已过时,建议用 ConcurrentHashMap

一如既往,文中所有示例代码可以在 GitHub 上找到。


原始标题:Differences Between HashMap and Hashtable in Java

« 上一篇: Akka HTTP 入门指南