1. 概述
这篇短文将聚焦在 Java 中 HashMap
和 Hashtable
的核心差异上。
2. Java 中的 Hashtable 与 HashMap
Hashtable
和 HashMap
非常相似 —— 它们都实现了 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
(枚举)
💡 Iterator
是 Enumeration
的改进版,支持 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. 小结
这篇文章总结了 HashMap
和 Hashtable
的几个关键差异点:
特性 | HashMap | Hashtable |
---|---|---|
线程安全 | ❌ 否 | ✅ 是 |
null 支持 | ✅ key/value 可以为 null | ❌ 不允许 null |
遍历方式 | Iterator (fail-fast) | Enumeration |
性能 | 更快 | 较慢(因同步) |
推荐使用场景 | 单线程或手动同步 | 已过时,建议用 ConcurrentHashMap |
一如既往,文中所有示例代码可以在 GitHub 上找到。