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

Hashtable 与 HashMap 的区别笔记

在 Java 中,HashtableHashMap 都是用于存储键值对的哈希表实现类,继承自 Map 接口。虽然它们都提供了类似的功能,但它们在性能、线程安全性、支持的特性等方面存在一些显著的区别。了解这些差异有助于在开发过程中选择适合的集合类。

1. 线程安全性

1.1 Hashtable

  • Hashtable线程安全的。在多线程环境下,Hashtable 使用**同步(Synchronized)**机制来确保每次只有一个线程能访问它的内部数据。
  • 这种同步机制会使得 Hashtable 在并发环境下能够避免数据不一致问题,但也会显著影响性能。因为在同一时间只有一个线程能够访问它的任意部分,导致线程在进行读写操作时会发生阻塞。

1.2 HashMap

  • HashMap非线程安全的。在多线程环境中,多个线程对 HashMap 进行修改时会产生不确定的结果,因此无法保证数据的一致性。
  • 如果需要在多线程环境中使用 HashMap,通常会使用外部同步手段(如 Collections.synchronizedMap()ReentrantLock)来确保线程安全。
小结:
  • Hashtable 是线程安全的,但性能较差。
  • HashMap 是非线程安全的,适合单线程或外部进行同步的情况。

2. 性能

2.1 Hashtable

由于 Hashtable 在每个操作上都进行同步,它在并发环境下会产生额外的性能开销。每次线程需要等待对 Hashtable 的访问,导致并发性能差。

2.2 HashMap

HashMap 由于不进行同步控制,它的性能通常优于 Hashtable,尤其在单线程环境下,或者在使用外部同步机制时。没有同步开销,读取和写入速度较快。

小结:
  • Hashtable 的性能较差,适合较低并发的场景。
  • HashMap 的性能更高,适合高并发的场景(需要外部同步)。

3. 空键和空值的支持

3.1 Hashtable

  • Hashtable 不允许键或值为 null。如果你尝试使用 null 作为键或值插入到 Hashtable 中,将会抛出 NullPointerException 异常。

3.2 HashMap

  • HashMap 允许一个 null 键和多个 null 值。null 键会被存储在哈希表的第一个位置,而多个 null 值则可以正常存储。
小结:
  • Hashtable 不允许 null 键和值。
  • HashMap 允许一个 null 键和多个 null 值。

4. 迭代器的不同

4.1 Hashtable

  • Hashtable 使用的是传统的 Enumerator 迭代器,虽然 HashtablekeySet()entrySet() 方法返回的是 Iterator,但它的底层实现是基于 Enumerator 的。
  • Enumerator 是在 VectorHashtable 中早期使用的一种迭代机制,但它已经过时,不支持 remove() 操作,也没有在迭代时抛出 ConcurrentModificationException 异常。

4.2 HashMap

  • HashMap 使用的是现代的 Iterator,它支持快速失败机制(fail-fast),即当集合结构在迭代过程中被修改时,会抛出 ConcurrentModificationException 异常。
  • 迭代时,如果其他线程在修改 HashMapIterator 会抛出异常。
小结:
  • Hashtable 使用的是过时的 Enumerator,不支持并发修改。
  • HashMap 使用支持并发修改检查的 Iterator

5. 扩容策略

5.1 Hashtable

  • Hashtable 在初次加载时,默认的初始容量为 11,负载因子为 0.75。扩容时会将容量扩大为原来的两倍,并且在扩容过程中会进行同步,导致性能进一步下降。
  • 扩容过程是全表锁定的,可能影响并发性能。

5.2 HashMap

  • HashMap 的默认初始容量为 16,负载因子为 0.75。与 Hashtable 相比,HashMap 在扩容时的效率更高。扩容时会将容量扩大为原来的两倍。
  • HashMap 的扩容也是线程不安全的,但它的性能优于 Hashtable,特别是在扩容操作中不需要全表加锁。
小结:
  • Hashtable 的扩容性能较差,尤其在高并发时。
  • HashMap 的扩容性能更好,适合高并发场景。

6. 类的继承关系

6.1 Hashtable

  • Hashtable 继承自 Dictionary 类,而 Dictionary 是一个过时的类,已经不再推荐使用。
  • Hashtable 实现了 Map 接口,但由于它继承自 Dictionary,其设计较为老旧。

6.2 HashMap

  • HashMap 直接实现了 Map 接口,并且不依赖于 Dictionary 类,是现代 Java 集合框架的标准实现类。
  • HashMap 是基于哈希表的实现,通常比 Hashtable 更灵活和高效。
小结:
  • Hashtable 继承自过时的 Dictionary 类。
  • HashMap 直接实现 Map 接口,符合现代 Java 集合设计。

7. 总结

特性HashtableHashMap
线程安全性线程安全(使用同步)非线程安全
性能由于同步机制,性能较差性能较好,尤其在单线程下
空键和空值支持不允许 null 键和值允许 null 键和多个 null
迭代器使用过时的 Enumerator,不支持并发修改使用现代的 Iterator,支持并发修改检查
扩容机制扩容时全表加锁,性能较差扩容时不加锁,性能优越
类的继承关系继承自 Dictionary继承自 Map 接口,符合现代设计

结论

  • 在现代 Java 开发中,Hashtable 已经不再被推荐使用。由于其线程安全的机制,它的性能在高并发场景下不如 HashMap,而且使用过时的 Dictionary 类。
  • HashMap 是更现代、更高效的选择,适用于大多数应用场景,尤其是在单线程环境或通过外部同步确保线程安全的情况下。如果需要线程安全的集合,推荐使用 ConcurrentHashMap,它提供了更好的并发性能和线程安全性。
http://www.lryc.cn/news/586909.html

相关文章:

  • LeetCode|Day9|976. 三角形的最大周长|Python刷题笔记
  • 代码部落 20250629 CSP-S复赛 模拟赛
  • 代码随想录算法训练营第十八天
  • 攻防世界——Web题 very_easy_sql
  • 解析磁盘文件系统
  • 面试150 从中序与后序遍历构造二叉树
  • 手写std::optional:告别空指针的痛苦
  • HTTP与HTTPS详解
  • 20250713 保存 PGM / PPM 图片 C++
  • COZE token刷新
  • 一文读懂现代卷积神经网络—使用块的网络(VGG)
  • 2025江苏省信息安全管理与评估赛项二三阶段任务书
  • 改进后的 OpenCV 5.x + GStreamer + Python 3.12 编译流程(适用于 Orange Pi / ARM64)
  • 3.7 ASPICE的问题解决与改进过程
  • Linux-网络管理
  • iTestin 自动化录制工具
  • Kimi K2深度解析:开源万亿参数大模型,复杂场景能力强悍,为AI Agent而生!
  • Vision Kit之文档扫描
  • 【PyMuPDF】PDF图片处理过程内存优化分析
  • 论文Review 3DGSSLAM GauS-SLAM: Dense RGB-D SLAM with Gaussian Surfels
  • kettle从入门到精通 第102课 ETL之kettle xxl-job调度kettle的两种方式
  • 归并排序递归法和非递归法的简单简单介绍
  • 三种网络类型
  • X00211-基于残差edge-graph注意力机制的深度强化学习优化车辆路径问题
  • RedisJSON 技术揭秘(五)`JSON.ARRPOP` 原子弹出 修改数组的终极手段
  • 基于Java Web的销售管理系统设计系统
  • 操作系统--用户态和内核态
  • MongoDB对接SpringBoot【大数据存储】
  • ref 和 reactive
  • https交互原理