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. 如果该桶是一棵红黑树,走红黑树新增和更新逻辑,同样新增的最后要看是否需要扩容
相关文章
|
消息中间件 数据库 RocketMQ
分布式事务常见解决方案
分布式事务常见解决方案
2895 0
|
消息中间件 SQL Java
Flink自定义Connector
Flink自定义Connector
1042 0
|
4月前
|
Java 数据库 微服务
Java 学习路线可按「基础→进阶→实战→架构」四阶段推进
Java学习路线分四阶段:基础→进阶→实战→架构。涵盖语法、多线程、框架、微服务等核心内容,搭配项目实战与学习技巧,助你系统掌握Java开发技能,逐步成长为高级工程师。(238字)
533 4
|
SQL 存储 大数据
Flink 基础详解:大数据处理的强大引擎
Apache Flink 是一个分布式流批一体化的开源平台,专为大规模数据处理设计。它支持实时流处理和批处理,具有高吞吐量、低延迟特性。Flink 提供统一的编程抽象,简化大数据应用开发,并在流处理方面表现卓越,广泛应用于实时监控、金融交易分析等场景。其架构包括 JobManager、TaskManager 和 Client,支持并行度、水位线、时间语义等基础属性。Flink 还提供了丰富的算子、状态管理和容错机制,如检查点和 Savepoint,确保作业的可靠性和一致性。此外,Flink 支持 SQL 查询和 CDC 功能,实现实时数据捕获与同步,广泛应用于数据仓库和实时数据分析领域。
10397 42
|
开发框架 Java 开发者
Spring Boot中的自动装配原理
Spring Boot中的自动装配原理
3696 1
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
30231 8
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
存储 算法 安全
大揭秘:HashMap原理解析
大揭秘:HashMap原理解析
662 0
|
设计模式 JSON JavaScript
前端开发人员使用的顶级 Node.js 框架介绍
前端开发人员使用的顶级 Node.js 框架介绍
1599 153
前端开发人员使用的顶级 Node.js 框架介绍
深入理解Spring Boot中的配置加载顺序
深入理解Spring Boot中的配置加载顺序
|
SQL 存储 Java
Hive 拉链表详解及实例
拉链表是一种数据仓库技术,用于处理持续增长且存在时间范围内的重复数据,以节省空间。它在Hive中通过列式存储ORC实现,适用于大规模数据场景,尤其当数据在有限时间内有多种状态变化。配置涉及事务管理和表合并选项。示例中展示了如何从原始订单表创建拉链表,通过聚合操作和动态分区减少数据冗余。增量数据可通过追加到原始表然后更新拉链表来处理。提供的Java代码用于生成模拟的订单增量数据,以演示拉链表的工作流程。
1009 3

热门文章

最新文章