HashMap 与 HashTable 的区别
HashMap 和 HashTable 都是 Java 中基于哈希表实现的 Map 接口的实现类,但它们有以下几个关键区别:
1. 线程安全性
HashMap | HashTable | |
---|---|---|
线程安全 | 非线程安全 | 线程安全 (方法使用 synchronized 修饰) |
同步 | 需要外部同步 | 内部同步 |
// HashMap 需要外部同步 Map<String, String> hashMap = new HashMap<>(); Map<String, String> syncMap = Collections.synchronizedMap(hashMap); // HashTable 内部同步 Map<String, String> hashTable = new Hashtable<>();
2. null 键/值处理
HashMap | HashTable | |
---|---|---|
null键 | 允许1个 | 不允许 |
null值 | 允许多个 | 不允许 |
HashMap<String, String> hm = new HashMap<>(); hm.put(null, "value"); // 允许 hm.put("key", null); // 允许 Hashtable<String, String> ht = new Hashtable<>(); ht.put(null, "value"); // 抛出 NullPointerException ht.put("key", null); // 抛出 NullPointerException
3. 性能比较
HashMap | HashTable | |
---|---|---|
性能 | 更高 | 较低 |
原因 | 无同步开销 | 同步方法带来性能损耗 |
4. 迭代器
HashMap | HashTable | |
---|---|---|
迭代器 | fail-fast | fail-fast |
(快速失败) | (快速失败) | |
枚举 | 不支持 | 支持 |
Hashtable<String, String> ht = new Hashtable<>(); Enumeration<String> keys = ht.keys(); // HashTable 特有
5. 继承体系
java.util.Dictionary (已废弃) ↑ Hashtable java.util.AbstractMap ↑ HashMap
6. 初始容量与扩容
HashMap | HashTable | |
---|---|---|
默认初始容量 | 16 | 11 |
扩容方式 | 2n | 2n+1 |
7. 使用建议
-
使用 HashMap 的情况:
-
单线程环境
-
需要更高的性能
-
需要存储 null 键/值
-
-
使用 HashTable 的情况:
-
遗留系统维护
-
需要线程安全且不介意性能损耗
-
不需要存储 null 键/值
-
8. 替代方案
对于线程安全的 Map 实现,更推荐使用:
-
ConcurrentHashMap
(JDK 1.5+) -
Collections.synchronizedMap()
ConcurrentHashMap 示例:
Map<String, String> concurrentMap = new ConcurrentHashMap<>(); // 比 HashTable 更高的并发性能
总结对比表
特性 | HashMap | HashTable |
---|---|---|
线程安全 | 不安全 | 安全(synchronized) |
null键值 | 允许 | 不允许 |
性能 | 更高 | 较低 |
迭代器 | Iterator | Iterator + Enumeration |
继承类 | AbstractMap | Dictionary |
初始容量 | 16 | 11 |
扩容方式 | 2n | 2n+1 |
推荐使用场景 | 单线程/高并发替代 | 遗留系统 |