讲师中心 微信公众号
AI工具推荐 视频效率加速

在Java里HashMap的put方法是如何执行的_Java数据存储流程解析

老涛同学_6805

老涛同学_6805

发布时间:2026-01-31 11:07:18

|

266人浏览过

|

来源于php中文网

原创

HashMap的put方法先调用hash(key)扰动计算hash值:null键hash为0,非null键用hashCode()高16位异或低16位;再通过(n-1)&hash定位索引,要求n为2的幂;冲突时遍历链表/红黑树,满足长度≥8且数组≥64才树化;超阈值触发扩容,全量rehash;key的hashCode与equals必须一致,禁用可变对象作key。

在java里hashmap的put方法是如何执行的_java数据存储流程解析

put方法执行时如何计算key的hash值

HashMap的put方法第一步不是直接插入,而是调用hash(key)对key做扰动运算。这个静态方法会把key的hashCode()高16位异或低16位,目的是让高位也参与寻址,缓解低位碰撞——尤其当数组长度是2的幂次时,只取低位做下标容易导致大量key落在同一桶里。

注意:null key被特殊处理,它的hash值固定为0,且总被放在数组索引0的位置。

如何确定元素存入哪个数组槽位(index)

算出hash值后,真正定位下标用的是位运算:(n - 1) & hash,其中n是table数组长度(必须是2的幂)。这等价于取模hash % n,但更快。前提是数组长度必须是2的幂,否则位运算结果不等于取模,会导致索引越界或分布不均。

常见坑:

立即学习“Java免费学习笔记(深入)”;

  • 手动传入初始容量如new HashMap(10),实际扩容后数组长度变成16(向上取最近2的幂),不是10
  • 如果重写了hashCode()但没重写equals(),可能造成逻辑错误:两个equal对象hash不同,被当作不同key存两次

发生哈希冲突后怎么处理链表与红黑树

当目标槽位(bucket)已有节点,HashMap会遍历该位置的链表或红黑树:

  • 先用==比引用,再用equals()比内容,找到相同key就覆盖value
  • 没找到则新节点插在链表尾部(JDK 8+,之前是头插,有并发死链风险)
  • 当链表长度≥8 且 数组长度≥64,链表转为红黑树;反之若数组太小,优先扩容而不是树化
  • 红黑树节点数≤6时,会退化回链表

所以“链表转树”不是单看长度,要同时满足两个条件,否则只是扩容。

扩容机制如何触发与影响性能

当size > threshold(即capacity × loadFactor)时触发扩容。默认初始容量16、负载因子0.75,所以第13个元素put时就会扩容到32。

扩容过程是全量rehash:新数组长度翻倍,所有旧节点重新计算index并迁移。这是put最耗时的部分,尤其在频繁put且未预估容量时,可能连续多次扩容。

建议:

  • 如果知道大概元素数量,初始化时指定容量:new HashMap(expectedSize / 0.75f + 1)
  • 避免在循环中反复put大量数据却不预设容量
  • 并发场景别用HashMap,ConcurrentHashMap的扩容是分段进行的,不影响读操作

真正难调试的点往往不在put逻辑本身,而在key的hashCode()和equals()实现是否自洽,以及是否无意中把可变对象当key用了——后者会让hash值随对象状态变化,导致get不到、remove失败、甚至内存泄漏。

热门AI工具

更多
蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

0

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

0

2026.10.22

Gradle怎么构建Java项目
Gradle怎么构建Java项目

本专题介绍Gradle Java项目构建方法,涵盖Java插件配置、依赖声明、源码编译、测试执行和打包检查,帮助你理解各阶段的任务关系,逐步完成项目构建。

0

2026.10.22

PHP时间戳漏洞修复教程
PHP时间戳漏洞修复教程

本专题汇总PHP常见时间戳漏洞,包括2038年溢出、时区漂移、时间戳伪造、重放攻击、时间盲注与日志审计失效等,并给出升级64位环境、使用 DateTimeImmutable、统一UTC、严格超时校验、预处理绑定、hash_equals 比对等修复方案,帮助开发者快速排查和加固时间相关代码。

0

2026.10.22

Golangci-lint配置文件与规则设置
Golangci-lint配置文件与规则设置

本专题聚焦Golangci-lint YAML配置文件,讲清运行参数、规则启停、目录排除、问题过滤及严重级别设置,便于团队统一检查标准。

0

2026.10.22

Golangci-lint安装与入门教程
Golangci-lint安装与入门教程

本专题讲解Golangci-lint的安装、初始化、基础命令和首次代码检查,覆盖本地环境、Docker及多平台用法,帮助Go开发者快速上手。

0

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn