HashMap 原理

简介: HashMap 底层采用数组、链表与红黑树结合的结构。通过 key 的 hashCode 定位数组索引,实现高效存取。当发生哈希冲突时,使用链表解决;链表过长则转化为红黑树,提升查找效率至 O(log n)。扩容时,默认容量为16,负载因子0.75,容量翻倍并重新计算索引。Put 方法流程包括:计算 hash、初始化数组、确定索引、处理冲突(链表或红黑树),并根据情况扩容或树化。

HashMap 原理(数据结构)
底层数据结构:数组+链表+红黑树
● 数组:存取元素时,利用 key 的 hashCode 来计算它在数组中的索引,这样在没有冲突的情况下,能让存取时间复杂度达到 O(1)
● 冲突:数组大小毕竟有限,就算元素的 hashCode 唯一,数组大小是 n 的情况下要放入 n+1 个元素,根据鸽巢原理,肯定会发生冲突
● 解决冲突:一种办法就是利用链表,将这些冲突的元素链起来,当然在在此链表中存取元素,时间复杂度会提高为 O(n)
接下来要能说出为什么在链表的基础上还要有红黑树
● 树化目的是避免链表过长引起的整个 HashMap 性能下降,红黑树的时间复杂度是 O(log{n})
有一些细节问题可以继续回答,比如树化的时机【进阶】
● 时机:在数组容量达到 >= 64 且 链表长度 >= 8 时,链表会转换成红黑树
● 如果树中节点做了删除,节点少到已经没必要维护树,那么红黑树也会退化为链表
HashMap 原理(扩容)
扩容因子:0.75 也就是 3/4
● 初始容量 16,当放入第 13 个元素时(超过 3/4)时会进行扩容
● 每次扩容,容量翻倍
● 扩容后,会重新计算 key 对应的桶下标(即数组索引)这样,一部分 key 会移动到其它桶中
HashMap 原理(方法执行流程)
以 put 方法为例进行说明

  1. 产生 hash 码。
    a. 先调用 key.hashCode() 方法
    b. 为了让哈希分布更均匀,还要对它返回结果进行二次哈希,这个结果称为 hash
    c. 二次哈希就是把 hashCode 的高 16 位与低 16 位做了个异或运算
  2. 搞定数组。
    a. 如果数组还不存在,会创建默认容量为 16 的数组,容量称为 n
    b. 否则使用已有数组
  3. 计算桶下标。
    a. 利用 (n - 1) & hash 得到 key 对应的桶下标(即数组索引)
    b. 也可以用 hash % n 来计算,但效率比前面的方法低,且有负数问题
    c. 用 (n - 1) & hash 有前提,就是容量 n 必须是 2 的幂(如 16,32,64 ...)
  4. 计算好桶下标后,分三种情况
    a. 如果该桶位置还空着,直接根据键值创建新的 Node 对象放入该位置即可
    b. 如果该桶是一条链表,沿着链表找,看看是否有值相同的 key,有走更新,没有走新增
    ■ 走新增逻辑的话,是把节点链到尾部(尾插法)
    ■ 新增后还要检查链表是否需要树化,如果是,转成红黑树
    ■ 新增的最后要检查元素个数 size,如果超过阈值,要走扩容逻辑
    c. 如果该桶是一棵红黑树,走红黑树新增和更新逻辑,同样新增的最后要看是否需要扩容
相关文章
|
11月前
|
消息中间件 分布式计算 大数据
大数据-113 Flink DataStreamAPI 程序输入源 自定义输入源 非并行源与并行源
大数据-113 Flink DataStreamAPI 程序输入源 自定义输入源 非并行源与并行源
126 0
|
8月前
|
SQL 存储 大数据
Flink 基础详解:大数据处理的强大引擎
Apache Flink 是一个分布式流批一体化的开源平台,专为大规模数据处理设计。它支持实时流处理和批处理,具有高吞吐量、低延迟特性。Flink 提供统一的编程抽象,简化大数据应用开发,并在流处理方面表现卓越,广泛应用于实时监控、金融交易分析等场景。其架构包括 JobManager、TaskManager 和 Client,支持并行度、水位线、时间语义等基础属性。Flink 还提供了丰富的算子、状态管理和容错机制,如检查点和 Savepoint,确保作业的可靠性和一致性。此外,Flink 支持 SQL 查询和 CDC 功能,实现实时数据捕获与同步,广泛应用于数据仓库和实时数据分析领域。
4023 32
|
存储 算法 Java
HashMap 之底层数据结构和扩容机制
HashMap 之底层数据结构和扩容机制
1581 1
|
消息中间件 SQL Java
Flink自定义Connector
Flink自定义Connector
758 0
|
8月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
360 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
6月前
|
人工智能 5G Windows
十分钟私有化部署DeepSeek R1
DeepSeek本地化部署支持下载1.5b、7b、8b、14b、32b等不同参数规模的大模型,适合逻辑推理和计算类问题。普通电脑建议选择1.5b模型以避免AI幻觉。部署需使用Ollama工具下载模型,并通过Chatbox AI等客户端进行配置,确保Ollama运行状态。显卡内存为主要资源占用,各模型占用情况不同,请确保硬盘空间充足。
865 11
|
存储 缓存 负载均衡
什么是CDN(内容分发网络)?
什么是CDN(内容分发网络)?
7122 7
|
消息中间件 存储 负载均衡
深入理解Kafka核心设计及原理(三):消费者
深入理解Kafka核心设计及原理(三):消费者
223 8
|
Java 应用服务中间件 Nacos
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
297 3
Spring Cloud 常用各个组件详解及实现原理(附加源码+实现逻辑图)
|
Java 应用服务中间件
idea tomcat 日志 中文 乱码【已解决】
idea tomcat 日志 中文 乱码【已解决】
731 0