当前位置: 首页 > 新闻动态 > 网络资讯

在Java中HashMap和Hashtable有什么区别_JavaMap线程安全解析

作者:P粉602998670 浏览: 发布日期:2026-01-30
[导读]:HashMap允许null键和null值,Hashtable不允许任何null;HashMap默认容量16(2的幂,位运算寻址),Hashtable默认11(奇数,取模寻址);HashMap有红黑树优化,Hashtable无;Hashtable迭代器不fail-fast,HashMap迭代器会抛ConcurrentModificationException。
HashMap允许null键和null值,Hashtable不允许任何null;HashMap默认容量16(2的幂,位运算寻址),Hashtable默认11(奇数,取模寻址);HashMap有红黑树优化,Hashtable无;Hashtable迭代器不fail-fast,HashMap迭代器会抛ConcurrentModificationException。

HashMap 和 Hashtable 谁能存 null?一写就报错的坑

这是开发中最常踩的雷:Hashtablenull 零容忍,只要 put(null, "x")put("k", null),立刻抛 NullPointerException;而 HashMap 允许一个 null 键(存在数组索引 0 的位置)和任意多个 null 值。

  • 如果你业务里需要把“未设置”“未知来源”等语义用 null 表达为 key,只

    能选 HashMap
  • Hashtable 时别依赖 IDE 自动补全——它不会提前告诉你 put 方法内部有 if (key == null) throw new NullPointerException()
  • 注意:即使你用 Collections.synchronizedMap(new HashMap())null 支持仍保留,但线程安全是“假安全”(全局锁,性能差)

多线程环境下直接用 Hashtable 真的安全吗?

语法上安全,逻辑上危险。它的所有方法都加了 synchronized,但锁的是整个对象——相当于排队打饭,一个人打完,下一个人才能进窗口。并发高时,getput 互相阻塞,吞吐量断崖下跌。

  • ConcurrentHashMap 是现代替代方案:JDK 1.8+ 用 CAS + synchronized 分段锁(实际是 Node 数组分桶加锁),读操作无锁,写操作只锁冲突桶
  • 千万别为了“图省事”在 Spring Bean 里注入 Hashtable 当共享缓存——哪怕 QPS 只有 50,响应延迟也可能翻倍
  • 如果必须兼容老代码且不能改类型,至少确认它没被高频 put / remove,否则扩容时的锁竞争会更严重

为什么 HashMap 默认容量是 16,而 Hashtable 是 11?

这不是随意定的数字,背后是哈希寻址效率差异:

  • HashMap 容量必须是 2 的幂(16、32、64…),这样算桶索引用位运算 hash & (capacity - 1),比取模快一个数量级
  • Hashtable 容量默认 11(奇数),扩容公式是 newCapacity = oldCapacity * 2 + 1,设计初衷是让 hash % capacity 分布更均匀——但现代 CPU 上,取模成本远高于位运算,这个优化已失效
  • 实测:插入 10 万条数据,HashMap 平均耗时约 8ms,Hashtable 约 14ms(JDK 17,无并发)

HashMap 的红黑树优化,Hashtable 为什么没有?

因为 Hashtable 是 JDK 1.0 的遗留类,从诞生就没考虑过海量哈希冲突场景;而 HashMap 在 JDK 1.8 引入红黑树,专门解决“链表过长 → 查询退化成 O(n)”的问题。

  • 触发条件很明确:链表长度 ≥ 8数组容量 ≥ 64,才转红黑树;反之,节点 ≤ 6 就降级回链表
  • 这意味着:如果业务中 key 的 hashCode() 实现不合理(比如总返回同一个值),Hashtable 的查询会随数据增长线性变慢,而 HashMap 仍能保持 O(log n)
  • 别指望靠调大 initialCapacity 规避——真正要治本,得重写 key 类的 hashCode()equals()

真正容易被忽略的点是:HashtableEnumeration 迭代器不支持 fail-fast,遍历时被其他线程修改也不会报错,结果可能漏数据或重复读;而 HashMapIterator 一旦检测到并发修改,立刻抛 ConcurrentModificationException——这看似是“缺点”,其实是帮你提前暴露线程安全问题。

免责声明:转载请注明出处:http://jing-feng.com.cn/news/772101.html

扫一扫高效沟通

多一份参考总有益处

免费领取网站策划SEO优化策划方案

请填写下方表单,我们会尽快与您联系
感谢您的咨询,我们会尽快给您回复!