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

HashMap和Hashtable

HashMapHashtable是 Java 中用于存储键值对的两个重要集合类,它们都基于哈希表实现,但在线程安全性、功能特性和使用场景上有显著区别。以下是详细解析:

一、核心区别总览

对比维度HashMapHashtable
线程安全性非线程安全线程安全(方法加synchronized
键值是否允许为 null允许keynull(最多一个),value可为多个null不允许keyvaluenull
继承关系继承AbstractMap继承Dictionary(已过时)
迭代器类型快速失败迭代器(fail-fast安全失败迭代器(fail-safe
性能高(无同步开销)低(同步开销大)
扩容机制初始容量 16,扩容为原容量的 2 倍初始容量 11,扩容为原容量的 2 倍 + 1
适用场景单线程环境或并发控制由用户处理的场景多线程环境(已被ConcurrentHashMap替代)

二、详细差异解析

1. 线程安全性
  • HashMap

    • 非线程安全,多个线程同时修改时可能导致数据不一致(如链表成环、元素丢失)。
    • 若需线程安全,可使用Collections.synchronizedMap(new HashMap<>())ConcurrentHashMap(推荐)。
  • Hashtable

    • 线程安全,所有方法都被synchronized修饰(对整个哈希表加锁)。
    • 缺点:多线程竞争时,锁竞争激烈,性能低下(同一时间只能有一个线程操作)。
2. 对 null 的支持
  • HashMap

    • 允许keynull(仅允许一个,重复添加会覆盖)。
    • 允许valuenull(可多个)。
    HashMap<String, String> map = new HashMap<>();
    map.put(null, "value1"); // 合法
    map.put("key2", null);   // 合法
    
  • Hashtable

    • 不允许keyvaluenull,否则会抛出NullPointerException
    Hashtable<String, String> table = new Hashtable<>();
    table.put(null, "value"); // 抛出NullPointerException
    table.put("key", null);   // 抛出NullPointerException
    
3. 继承关系与历史
  • HashMap

    • 诞生于 JDK 1.2,继承AbstractMap类,完全遵循Map接口规范。
  • Hashtable

    • 诞生于 JDK 1.0,继承古老的Dictionary类(已被废弃),后来才实现Map接口。
    • 设计上存在历史遗留问题,如方法命名(elements()而非values())。
4. 迭代器特性
  • HashMap

    • 使用快速失败迭代器(fail-fast:迭代过程中若修改地图结构(如添加 / 删除元素),会立即抛出ConcurrentModificationException
    • 原理:通过modCount(修改次数)检测结构变化。
  • Hashtable

    • 使用安全失败迭代器(fail-safe:迭代器基于集合的副本工作,迭代过程中修改原集合不会抛出异常(但可能读取到旧数据)。
    • 缺点:副本占用额外内存,且无法保证数据实时性。
5. 扩容机制
  • HashMap

    • 初始容量:16(必须为 2 的幂)。
    • 扩容阈值:当元素数量 > 容量 × 负载因子(默认 0.75)时,扩容为原容量的 2 倍
    • 哈希计算:(n - 1) & hash(利用位运算高效计算索引,因容量为 2 的幂)。
  • Hashtable

    • 初始容量:11(非 2 的幂)。
    • 扩容阈值:当元素数量 > 容量 × 负载因子(默认 0.75)时,扩容为原容量 × 2 + 1
    • 哈希计算:hash % n(取模运算,效率低于位运算)。
6. 性能对比
  • HashMap

    • 无同步锁开销,单线程环境下性能远高于Hashtable
    • 支持红黑树优化(JDK 8+),极端情况下查询效率更优。
  • Hashtable

    • 所有方法加锁,多线程竞争时性能差(尤其是高并发场景)。
    • 无红黑树优化,长链表查询效率低。

三、代码示例对比

import java.util.HashMap;
import java.util.Hashtable;public class MapComparison {public static void main(String[] args) {// HashMap示例HashMap<String, Integer> hashMap = new HashMap<>();hashMap.put(null, 10);    // 允许key为nullhashMap.put("apple", null); // 允许value为nullSystem.out.println(hashMap.get(null)); // 输出:10// Hashtable示例Hashtable<String, Integer> hashtable = new Hashtable<>();// hashtable.put(null, 20); // 抛出NullPointerException// hashtable.put("banana", null); // 抛出NullPointerExceptionhashtable.put("orange", 30);System.out.println(hashtable.get("orange")); // 输出:30}
}

四、使用场景建议

  1. 优先选择HashMap

    • 单线程环境(如普通业务逻辑、工具类)。
    • 需要存储null键或值的场景。
    • 对性能要求较高的场景。
  2. 谨慎使用Hashtable

    • 仅在维护旧代码时使用(历史遗留系统)。
    • 多线程场景应改用ConcurrentHashMap(并发安全且性能更高)。

总结

HashMapHashtable的核心差异源于设计年代和线程安全策略:

  • HashMap是 JDK 1.2 引入的现代实现,牺牲线程安全换取高性能,支持null值,适合单线程场景。
  • Hashtable是 JDK 1.0 的古老实现,通过全表加锁保证线程安全,性能低下且不支持null,已被ConcurrentHashMap替代。

实际开发中,HashMap是默认选择;多线程场景推荐ConcurrentHashMap,而非Hashtable

http://www.dtcms.com/a/415859.html

相关文章:

  • 做个网站得花多少钱建成区违法建设治理网站
  • 革新深层水平位移监测——安锐科技推出全新节段式位移计,以模块化设计显著降低成本
  • 赣州企业网站在那做网站域名的管理密码如何索取
  • 网站建设与管理大纲天津科技公司网站
  • 网站开发与维护是什么企业网站需要什么功能
  • 【有源码】基于python+spark的餐饮外卖平台综合分析系统-基于Hadoop生态的外卖平台数据治理与分析系统
  • 【心力建设】《毛选》里的心法
  • 浙江网站建设有哪些合肥seo排名优化
  • 如何制作课程网站模板用python做网站的步骤
  • 光纤测温技术:原理与应用全解析
  • ICICLE-Snark:目前最快的 Groth16 实现
  • 做网站建设的公司seo优化网站推广
  • 网站原型设计和版式设计湖南手机版建站系统开发
  • 黔南网站建设做网站多大上行速度
  • m 外贸网站阿里巴巴可以做公司网站吗
  • 太仓网站建设有限公司网站备案域名证书
  • 家用机做网站服务器企业网站多大空间
  • 网站做sem优化全国卫生机构建设管理系统网站
  • 优质网站建设价格天津网站建设哪里好
  • 建设银行网站号圣诞网站源码
  • 多合一网站建设网站漂浮
  • 金华高端网站设计wordpress图片主题模板下载
  • 昌吉网站建设电话菠萝蜜影视传媒有限公司
  • 谷歌建站哪家好企业免费建站网站
  • 10. C++ 类—构造函数
  • 网站建设与制作设计公司洛阳网站设计哪家专业
  • 湘潭网站建设 w磐石网络中国能源建设集团有限公司是央企
  • 网站建设中间件收费游戏网站建设的策划
  • 关于单片机的原理与应用!
  • 电子商务网站建设与电子支付hao123网址怎么删除