HashTable详解

📅 2026/7/13 4:36:34 👁️ 阅读次数 📝 编程学习
HashTable详解

哈希表(HashTable)

  • 一个线程安全的哈希表实现,也叫散列表
  • 实现了Map接口,存储key-value 键值对
  • key 和 value 都不能为 null
  • O (1) 平均时间复杂度插入、删除、查找的数据结构
  • 方法都加了synchronized锁,所以线程安全
  • JDK 1.0 就有,非常古老,现在基本不用,但面试 / 老项目会遇到

一、核心概念

1. 哈希函数(Hash Function)

把任意长度的转换成固定长度的数组下标的函数。 公式:数组索引 = 哈希函数(键)

2. 哈希冲突(Hash Collision)

两个不同的键,通过哈希函数算出了同一个索引,这就是冲突。

哈希表必须解决冲突,常用方案:

  • 链地址法(拉链法):数组每个位置挂一个链表 / 红黑树(主流,如 HashMap)
  • 开放寻址法:冲突时向后找空位置存放(如 ThreadLocalMap)

二、哈希表工作原理(极简流程)

  1. 初始化一个固定 / 动态扩容的数组
  2. 存入键值对:用哈希函数计算键的索引
  3. 找到对应位置存放数据
  4. 查找 / 删除:直接通过哈希函数定位索引,无需遍历整个数组

三、相关数据结构对比

1. 哈希表 vs 数组 vs 链表

结构查找插入 / 删除适用场景
数组O(n)O(n)数据少、有序遍历
链表O(n)O(1)频繁插入删除
哈希表O(1)O(1)快速查找、键值对存储

2. HashTable vs HashMap

对比项HashMapHashTable
线程安全非安全安全(所有方法加 synchronized)
锁机制无锁锁整个哈希表(全表锁)
性能非常快很慢(高并发下性能极差)
key/value 是否允许 nullkey 允许 1 个 null,value 允许多个都不允许 null,否则 NPE
底层结构JDK8:数组 + 链表 + 红黑树数组 + 链表(无红黑树
默认容量1611
扩容方式扩容为原来的 2 倍扩容为原来的 2 倍 + 1
哈希计算优化过,扰动函数简单哈希计算
迭代器快速失败(fail-fast)安全失败(fail-safe)
父类继承 AbstractMap继承 Dictionary
推荐使用✅ 推荐(日常开发 99%)❌ 不推荐(老项目兼容)

关键区别:

1)线程安全 vs 非安全

  • HashMap无锁→ 单线程飞快,多线程会数据错乱、覆盖、死循环。
  • HashTable所有方法都加 synchronized→ 多线程安全,但整个表只能一个线程操作,性能极低。

2)是否允许 null

  • HashMap:key 可以存1 个 null,value 可以多个 null。
  • HashTablekey、value 都不能为 null,否则直接空指针异常。

3)性能差距巨大

  • HashMap:无锁,高吞吐。
  • HashTable:锁整张表,高并发下性能差

四、Java中的哈希表

  • Hashtable:JDK 原生哈希表,老旧、全表锁、线程安全,现在基本不用
  • HashMap:主力哈希表,非线程安全,查询 / 增删效率极高
  • ConcurrentHashMap:并发场景专用,线程安全、高性能
  • HashSet:底层基于HashMap,只存 key,用来去重

底层统一模型:数组 + 哈希函数 + 拉链法(链表 / 红黑树)

五、HashTable的实际用途

1. 多线程安全的键值存储

用途: 在多个线程同时读写数据时,保证数据不混乱、不丢失、不出现异常。

例如:

  • 简单的共享配置存取
  • 老项目中的共享计数器
  • 多线程日志记录、标记

2. 存在性判断、去重

用途: 判断某个 key 是否已经存在

例如:

  • 重复请求拦截
  • 黑名单校验
  • 任务去重

3. 简单线程安全缓存

用途: 把不常变的数据缓存到内存,提高访问速度。

例如:

  • 字典数据
  • 系统配置
  • 固定映射关系

4. 线程安全计数统计

用途: 多线程环境下统计次数

例如:

  • 接口访问次数
  • 用户点击次数
  • 任务执行次数

六、HashMap的实际用途

1. 存储键值对映射(最常用):

  • 封装接口参数、返回结果
  • 状态码映射、字典配置
  • 临时数据组装、对象关联

2. 快速查找、判断存在:

  • 判断用户是否存在
  • 判断手机号是否重复
  • 黑名单、白名单校验
  • 缓存命中判断

3. 数据去重:

  • 列表去重
  • 日志去重
  • 批量数据去重

4. 数据分组 / 一对多归集:

  • 按分类分组商品
  • 按状态分组订单
  • 按部门分组员工

5. 本地缓存(热点数据):

  • 缓存字典、配置、权限、地区数据
  • 减少数据库查询
  • 提升接口速度