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

相关推荐
MX_93592 小时前
Spring MVC拦截器
java·后端·spring·mvc
橘子编程2 小时前
MindOS:你的AI第二大脑知识库
java·开发语言·人工智能·计算机网络·ai
XWalnut2 小时前
LeetCode刷题 day9
java·算法·leetcode
忧郁的Mr.Li2 小时前
JAVA工具类---PDF电子签章工具类
java·pdf
零二年的冬2 小时前
epoll详解
java·linux·开发语言·c++·链表
凭君语未可2 小时前
Java 中的接口是什么
java·开发语言
XiYang-DING2 小时前
【Java】二叉树
java·开发语言·数据结构
凌冰_2 小时前
Servlet+Thymeleaf + Fetch 实现无刷新异步请求
java·servlet
深蓝轨迹3 小时前
面试常见的jdk---LTS版本新特性梳理
java·面试·jdk