HashMap、Hashtable、ConcurrentHashMap 核心对比

HashMap、Hashtable、ConcurrentHashMap 核心对比

一、整体概览

  • HashMap :单线程高性能,线程不安全
  • Hashtable :古老集合,全表 synchronized,线程安全但效率极低
  • ConcurrentHashMap :线程安全,分段锁 / CAS + synchronized,高并发首选

二、核心区别速查表

对比项 HashMap Hashtable ConcurrentHashMap
线程安全 ❌ 不安全 ✅ 安全 ✅ 安全
锁机制 无锁 方法全加 synchronized JDK7:分段锁 Segment JDK8:CAS + synchronized
效率 最高 最低 高(并发性能远胜 Hashtable)
key/value 是否允许 null key/value 都可 null key/value 都禁止 null key/value 都禁止 null
继承 继承 AbstractMap 继承 Dictionary 继承 AbstractMap
默认容量 16 11 16
扩容 容量 ×2 容量 ×2+1 同 HashMap
哈希冲突 JDK7:数组+链表 JDK8:数组+链表+红黑树 数组+链表 JDK8:数组+链表+红黑树
迭代器 快速失败 fail-fast 快速失败 fail-fast 安全失败 fail-safe

三、详细说明

1. HashMap(最常用)

  • 单线程环境下性能最好
  • 线程不安全,高并发会出现数据丢失、死循环
  • key 和 value 都可以为 null(只能有一个 key 为 null)
  • JDK8 优化:链表长度 ≥8 转为红黑树,≤6 退化为链表
  • 扩容机制:达到负载因子 0.75 时扩容为原来 2 倍

2. Hashtable(基本废弃)

  • 线程安全靠 方法级别 synchronized
  • 锁整个哈希表,并发能力极差
  • 不允许 null key / null value
  • 历史遗留类,不推荐使用

3. ConcurrentHashMap(高并发标准方案)

JDK 1.7
  • 采用 Segment 分段锁
  • 默认 16 个 Segment,每段一把锁
  • 支持 16 个线程并发
JDK 1.8(重大优化)
  • 取消 Segment,直接用 数组 + 链表 + 红黑树
  • 锁粒度降低:只锁链表/红黑树的头节点
  • 读操作无锁,使用 CAS + volatile
  • 写操作使用 synchronized + CAS
  • 并发性能大幅提升

四、底层扩容机制(通用)

  1. 初始容量默认 16
  2. 负载因子默认 0.75
  3. 元素数量 > 容量 × 0.75 时触发扩容
  4. 扩容为 原容量 × 2
  5. 重新计算所有元素哈希位置

五、为什么 ConcurrentHashMap 不允许 null?

  • 多线程场景下,get(key) == null 无法区分是 key 不存在 还是 value 为 null
  • 为避免歧义,严格禁止 null

HashMap 单线程无歧义,所以允许 null。


六、使用场景总结

  1. 单线程 → 用 HashMap
  2. 高并发 → 用 ConcurrentHashMap
  3. Hashtable → 基本废弃,不要用

七、高频面试题

  1. HashMap 为什么线程不安全?

    多线程同时扩容可能形成环形链表,导致死循环;同时 put 可能覆盖值。

  2. ConcurrentHashMap 在 JDK7 和 JDK8 的区别?

    JDK7:Segment 分段锁

    JDK8:CAS + synchronized + 红黑树,锁粒度更小,性能更高。

  3. 为什么 HashMap 允许 null,ConcurrentHashMap 不允许?

    多线程无法区分 null 是没找到还是值本身为 null。

  4. HashMap 哈希冲突怎么解决?

    链地址法,JDK8 加入红黑树优化。

相关推荐
步行cgn4 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风4 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae5 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路5 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog6 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog6 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz6 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_2518364577 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
caoerzhong7 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源
曹牧8 小时前
Java集合框架:List、ArrayList、Map 和 HashMap
java