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

相关推荐
keep one's resolveY17 分钟前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克31 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠2 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌2 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局2 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源2 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it2 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java
消失的旧时光-19433 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解
NE_STOP3 小时前
Redis--发布订阅命令和Redis事务
java
PAC_3Dame3 小时前
记一次真实的线上OOM
java