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 加入红黑树优化。

相关推荐
莫逸风11 小时前
【AgentScope 2.0】 0. 学习指南
java·llm·agent·agentscope
z1234567898611 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
yaoxin52112312 小时前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python
做个文艺程序员12 小时前
Linux第24篇:Java应用监控体系搭建:Prometheus+Grafana可视化运维
java·grafana·prometheus
小钻风336613 小时前
Spring Boot 文件上传详解:深入理解 MultipartFile 的使用与原理
java·开发语言
其美杰布-富贵-李13 小时前
Spring Boot 工程开发全流程说明
java·spring boot·后端
前端双越老师15 小时前
如何以前端视角(非0基础)学 Java ?
java·node.js·全栈
dear_bi_MyOnly15 小时前
【SpringBoot配置文件】
java·spring boot·后端·学习·spring·java-ee·学习方法
做个文艺程序员15 小时前
Linux第22篇:用Docker容器化你的Java SaaS应用:一次构建,随处运行
java·docker·容器
其美杰布-富贵-李16 小时前
Spring Boot 依赖注入说明文档
java·spring boot·python