当前位置: 首页 > news >正文

HashMap与Hashtable的关键区别

一、先明确核心定位

  • HashMap:Java 集合框架中非线程安全的哈希表实现,追求极致的单线程性能,是日常开发中最常用的键值对存储容器。
  • Hashtable:Java 早期(JDK 1.0)提供的线程安全的哈希表实现,设计较为简单粗暴,目前已基本被ConcurrentHashMap替代。

二、HashMap 与 Hashtable 详细区别

我会从核心维度拆解,每个维度都说明具体差异和背后的原因:

维度HashMapHashtable
1. 线程安全性非线程安全线程安全,但实现方式极 “笨重”
2. 锁机制无锁,所有操作均不做同步处理所有方法(put/get/remove/size 等)都用synchronized修饰,本质是全表加锁:- 任何线程操作 Hashtable 时,都会锁住整个哈希表;- 即使两个线程操作不同的 key,也会互相阻塞,并发性能极差。
3. 空值(null)支持允许:- key 可以为 null(仅允许 1 个,因为 hash 值固定为 0);- value 可以为 null(多个)。禁止:- 无论是 key 还是 value,传入 null 都会直接抛出NullPointerException;- 原因:Hashtable 设计时认为 null 会导致歧义,且同步场景下判空会增加复杂度。
4. 底层实现 / 结构JDK 1.8 后:数组 + 链表 + 红黑树(链表长度≥8 且数组长度≥64 时转红黑树);JDK 1.7:数组 + 链表。始终是数组 + 链表,从未支持红黑树优化;底层数组默认大小、扩容阈值等也有差异(见下文)。
5. 哈希计算方式JDK 1.8 优化了哈希算法:key.hashCode () → 扰动函数(减少哈希冲突) →(n - 1) & hash(取模,高效)。直接使用key.hashCode() % table.length取模(取模运算效率低于位运算);无扰动函数,哈希冲突概率更高。
6. 初始容量与扩容- 初始容量:默认 16;- 扩容阈值:默认负载因子 0.75,当size > 容量 * 负载因子时扩容;- 扩容规则:容量翻倍(×2);- 支持手动指定初始容量(会向上取整为 2 的幂)。- 初始容量:默认 11;- 扩容阈值:默认负载因子 0.75;- 扩容规则:容量变为2 * 原容量 + 1(非 2 的幂,进一步降低取模效率);- 手动指定的初始容量不会取整,直接使用。
7. 迭代器特性快速失败(fail-fast):迭代过程中如果其他线程修改了 HashMap 结构(增 / 删节点),迭代器会立即抛出ConcurrentModificationException;注意:单线程下如果迭代时自己修改(如 remove),也会触发。枚举器(Enumeration)是快速失败的;如果通过keySet().iterator()获取迭代器,同样是 fail-fast 特性。
8. 继承体系继承AbstractMap类,实现Map接口。继承Dictionary类(已废弃),实现Map接口;Dictionary是早期的键值对容器,设计上不如AbstractMap优雅。
9. 性能表现单线程下性能极高:无锁开销,哈希计算和扩容更高效。无论单线程 / 多线程,性能都差:- 单线程:全表锁无意义,还增加同步开销;- 多线程:全表锁导致并发度极低,线程竞争激烈时性能暴跌。
10. 使用场景单线程 / 低并发场景(如方法内局部变量、单例中的静态变量且仅单线程操作)。几乎无推荐场景:- 线程安全场景优先用ConcurrentHashMap(并发性能高);- 低并发线程安全场景也可使用Collections.synchronizedMap(new HashMap())(比 Hashtable 灵活)。

三、补充:Hashtable 被淘汰的核心原因

  1. 并发性能极差:全表锁导致多线程下几乎是串行执行,而ConcurrentHashMap仅锁单个桶,并发度提升数十倍。
  2. 设计老旧:基于废弃的Dictionary类,哈希计算、扩容规则等都未做优化,性能远不如 HashMap,更不如 ConcurrentHashMap。
  3. 功能限制:不支持 null 值,使用场景被进一步压缩。

四、代码示例:直观感受差异

1. 空值支持差异
public class HashMapVsHashtable { public static void main(String[] args) { // HashMap 支持 null key/value HashMap<String, String> hashMap = new HashMap<>(); hashMap.put(null, "nullKey"); hashMap.put("key1", null); System.out.println("HashMap null key: " + hashMap.get(null)); // 输出:nullKey System.out.println("HashMap null value: " + hashMap.get("key1")); // 输出:null // Hashtable 不支持 null,抛 NullPointerException Hashtable<String, String> hashtable = new Hashtable<>(); try { hashtable.put(null, "nullKey"); // 直接抛异常 } catch (NullPointerException e) { System.out.println("Hashtable 不支持 null key"); } try { hashtable.put("key1", null); // 直接抛异常 } catch (NullPointerException e) { System.out.println("Hashtable 不支持 null value"); } } }
2. 线程安全差异(多线程操作)
import java.util.HashMap; import java.util.Hashtable; public class ThreadSafetyTest { private static HashMap<String, Integer> hashMap = new HashMap<>(); private static Hashtable<String, Integer> hashtable = new Hashtable<>(); public static void main(String[] args) throws InterruptedException { // 测试 HashMap 线程不安全:多线程put可能导致死循环/数据丢失 Runnable hashMapTask = () -> { for (int i = 0; i < 1000; i++) { hashMap.put(Thread.currentThread().getName() + i, i); } }; // 测试 Hashtable 线程安全:不会出现数据错乱,但并发慢 Runnable hashtableTask = () -> { for (int i = 0; i < 1000; i++) { hashtable.put(Thread.currentThread().getName() + i, i); } }; Thread t1 = new Thread(hashMapTask); Thread t2 = new Thread(hashMapTask); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("HashMap 最终大小(可能≠2000):" + hashMap.size()); // 数据丢失/错乱 Thread t3 = new Thread(hashtableTask); Thread t4 = new Thread(hashtableTask); t3.start(); t4.start(); t3.join(); t4.join(); System.out.println("Hashtable 最终大小(一定=2000):" + hashtable.size()); // 数据完整 } }

总结

  1. 核心差异HashMap非线程安全、支持 null、单线程性能高;Hashtable线程安全(全表锁)、不支持 null、并发性能极差。
  2. 使用选择:单线程用HashMap,多线程安全场景优先用ConcurrentHashMap(而非 Hashtable)。
  3. 设计层面:Hashtable 是早期设计的产物,哈希计算、扩容、锁机制均无优化,现已被淘汰,仅作历史知识点了解即可。
http://www.jsqmd.com/news/440841/

相关文章:

  • Python flask微信小程序基于Android的艺术拍卖文化交流平台的设计与实现_r70jc04u
  • 换根 DP 经典模型:O(N) 求解树上经过每个节点的最长路径
  • 公司下属(信息学奥赛一本通- P2141)
  • 国内用户狂喜!NanoBananaPro 免费白嫖+API接入全攻略
  • 逆向如何学习?
  • 2026年2月AI王炸清单:大厂卷疯了,国产模型杀疯了!
  • 工作总结-日志打印
  • 20260305之所思 - 人生如梦
  • 告别笔记杂乱!Trilium Notes+cpolar,随时随地管好你的知识库
  • 哈尔滨69中六年级上册英语(人教版)全6单元导学案|学生版+教师版双配套
  • [学习笔记]trpo——对策略进行显式约束
  • 谷歌NanoBanana 2太强了,一文看懂如何使用!
  • 20260305 - 个人小作品更新
  • 数据库领域 ETL 工具大比拼,谁是王者?
  • 大数据领域数据服务的医疗数据服务
  • 【计算机毕业设计】基于Springboot的民宿预订小程序+LW
  • 复习总结
  • 价值投资中的智能城市地下空间规划系统分析
  • 概率论与数理统计学习笔记(大一第二学期)
  • 作为一个十年老痛风,我尝试了无数方法,在2026年总算找到了终极降尿酸正解 - 品牌企业推荐师(官方)
  • 从一只龙虾到一支团队:OpenClaw 单 Bot 多 Agent 配置实践
  • 2026年美国空派双清包税专线推荐-权威测评综合实力榜单 - 品牌企业推荐师(官方)
  • 早晚代餐怎么选才不踩坑?2026年减脂代餐实测报告,上班族轻松瘦身指南 - 品牌企业推荐师(官方)
  • 2026年房产中介管理系统采购避坑指南:这五个功能必须有 - 品牌企业推荐师(官方)
  • 聚焦同城老板资源对接,助品会打造高效创业生态圈 - 品牌企业推荐师(官方)
  • FPGA篇---LUT(查找表):FPGA 的“万能逻辑引擎”
  • 杭州猎头公司怎么选?推荐南方新华猎头公司2026年3月更新 - 品牌企业推荐师(官方)
  • 测试测试07测试测试07测试测试07测试测试07测试测试07
  • 当您需要被更多客户“看见”:联系福州睿象科技完整指引 - 品牌企业推荐师(官方)
  • 营养早餐不将就!2026早晚代餐实测封神:上班族不挨饿、不费脑,轻松瘦出好体态 - 品牌企业推荐师(官方)