Java中的HashMap实现原理深入理解

 更新时间:2025年12月11日 09:33:45   作者:im_winter185  
HashMap是一种非常常见和实用的数据结构,它被广泛应用于Java编程中,这篇文章主要介绍了Java中HashMap实现原理的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、前言

在 Java 开发中,HashMap 是我们最常用的集合类之一。无论是缓存、配置存储,还是数据传输,HashMap 都扮演着重要角色。但你是否真正了解它的底层实现?为什么它查找这么快?什么时候会退化成链表?JDK1.8 之后又有哪些优化?

本文将带你深入理解 HashMap 的实现原理,帮助你从“会用”到“懂原理”。

二、HashMap 的基本结构

1. 底层数据结构(JDK 1.8 之前 vs 之后)

版本数据结构
JDK 1.7数组 + 链表
JDK 1.8数组 + 链表 + 红黑树

解释:

  • 数组HashMap 的主干是一个 Node<K,V>[] table,每个元素是一个桶(bucket)。

  • 链表:当发生哈希冲突时,多个键值对会以链表形式存储在同一个桶中。

  • 红黑树:当链表长度超过 8 且数组长度大于 64 时,链表会转为红黑树,提升查询效率。

三、核心源码解析

1. 构造函数与初始容量

public HashMap(int initialCapacity, float loadFactor) {
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);
}
  • initialCapacity:初始容量,必须是 2 的幂。

  • loadFactor:负载因子,默认是 0.75,用于控制扩容时机。

2. put 方法流程

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

步骤如下:

  1. 计算 key 的 hash 值(hash(key)

  2. 定位桶位置((n - 1) & hash

  3. 如果桶为空,直接插入

  4. 如果桶不为空,遍历链表或红黑树

  5. 如果 key 已存在,覆盖 value

  6. 如果插入后长度超过阈值,触发扩容或树化

3. 哈希函数设计

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

目的: 减少哈希冲突,让高位也参与运算,提升分布均匀性。

四、扩容机制(resize)

当元素个数超过 threshold = capacity * loadFactor 时,会触发扩容:

  • 容量翻倍(newCap = oldCap << 1

  • 重新计算每个元素的位置(要么在原位置,要么在原位置 + oldCap)

优化点: JDK 1.8 中不需要重新计算 hash,只需看新增的那一位是 0 还是 1。

五、线程安全问题

⚠️ HashMap 是线程不安全的!

问题表现:

  • 多线程 put 可能导致链表成环(JDK 1.7)

  • 数据丢失、覆盖等问题

解决方案:

方式说明
Collections.synchronizedMap()包装器,性能差
ConcurrentHashMap推荐,分段锁/CAS 实现,线程安全且高效

六、面试高频问题总结

问题简答
HashMap 的底层结构?数组 + 链表 + 红黑树(JDK 1.8)
为什么容量必须是 2 的幂?位运算效率高,hash & (n-1) 替代取模
什么时候转红黑树?链表长度 > 8 且数组长度 > 64
为什么加载因子是 0.75?平衡空间与时间效率
如何线程安全地使用 Map?使用 ConcurrentHashMap

七、总结思维导图(文字版)

HashMap
├── 结构:数组 + 链表 + 红黑树
├── 核心方法:put、get、resize、hash
├── 优化:树化、扩容、hash 散列
├── 线程安全:ConcurrentHashMap
└── 面试点:容量、负载因子、冲突处理、树化条件

八、附录:手写一个简易 HashMap(练习)

public class MyHashMap<K, V> {
    private Node<K, V>[] table;
    private int size;

    static class Node<K, V> {
        final int hash;
        final K key;
        V value;
        Node<K, V> next;

        Node(int hash, K key, V value, Node<K, V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
    }

    public void put(K key, V value) {
        // 简化版,省略扩容、树化等逻辑
    }

    public V get(K key) {
        // 简化版
        return null;
    }
}

九、结语

理解 HashMap 的底层实现,不仅能帮助你在面试中脱颖而出,更能在实际开发中避免踩坑。希望本文能为你打下坚实的基础。

如果你觉得这篇文章对你有帮助,欢迎点赞、收藏、评论!
后续我还会更新《ConcurrentHashMap 源码解析》《Java 集合框架全景图》等内容,记得关注我哦!

十、参考资料

到此这篇关于Java中的HashMap实现原理的文章就介绍到这了,更多相关Java HashMap实现原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringCloud Feign请求头删除修改的操作代码

    SpringCloud Feign请求头删除修改的操作代码

    这篇文章主要介绍了SpringCloud Feign请求头删除修改,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • Mybatis-plus的selectPage()分页查询不生效问题解决

    Mybatis-plus的selectPage()分页查询不生效问题解决

    本文主要介绍了Mybatis-plus的selectPage()分页查询不生效问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • java selenium Selenium IDE介绍及用法

    java selenium Selenium IDE介绍及用法

    本文主要介绍java selenium Selenium IDE,这里整理了相关资料和介绍如何安装 Selenium IDE和使用方法,有需要的小伙伴可以参考下
    2016-08-08
  • type-aliases-package的用法解读

    type-aliases-package的用法解读

    在Mybatis的mapper.xml文件中使用type-aliases-package可以简化resultType和parameterType的全类名指定,通过配置扫描指定包中的实体类,让Mybatis自动识别这些实体
    2024-11-11
  • Java8 Optional常用方法使用场景分析

    Java8 Optional常用方法使用场景分析

    这篇文章主要介绍了Java8 Optional常用方法使用场景,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 关于SpringBoot获取IOC容器中注入的Bean(推荐)

    关于SpringBoot获取IOC容器中注入的Bean(推荐)

    本文通过实例代码给大家详解了springboot获取ioc容器中注入的bean问题,非常不错,具有一定的参考借鉴价值,需要的朋友参考下吧
    2018-05-05
  • Java JDK 二分法 分析demo(推荐)

    Java JDK 二分法 分析demo(推荐)

    下面小编就为大家带来一篇Java JDK 二分法 分析demo(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 解决springboot文件上传提示临时文件夹不存在问题

    解决springboot文件上传提示临时文件夹不存在问题

    这篇文章主要介绍了解决springboot文件上传提示临时文件夹不存在问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • MyBatis-Plus多表联查(动态查询)的项目实践

    MyBatis-Plus多表联查(动态查询)的项目实践

    本文主要介绍了MyBatis-Plus多表联查(动态查询)的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 基于@JsonFormat的导包问题

    基于@JsonFormat的导包问题

    这篇文章主要介绍了关于@JsonFormat的导包问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08

最新评论