HashMap详解-内部实现原理(1)-数组和桶

引言

HashMap 是 Java 中非常常用的数据结构,在实际开发中被广泛使用,经常被用于集合框架、程序开发、数据库连接、实现缓存与并发的情况,与ArrayList、HashSet 等同为常用集合的一员,所以对HashMap的了解是必要的。

HashMap的内部实现原理

HashMap的实现主要包括以下几个部分:数组和桶、哈希函数、哈希冲突的解决和扩容的方法

数组和桶

HashMap 内部具有一个数组,称为 table,用于存储键值对。每个数组元素是一个桶(bucket),可以容纳一个或多个键值对。桶的索引位置是根据键的哈希值计算得到的,我们以实现角度来分别描述。

  • 数组实现:HashMap 内部使用一个数组来存储元素,这个数组被称为表(table)。表的大小由初始化时指定的容量决定,它的长度是固定的。数组中的每个元素可以存放多个键值对。

  • 桶实现:每个数组元素称为一个桶(bucket),它可以存储一个或多个键值对。当发生哈希冲突时,即两个或多个键映射到同一个桶时,这些键值对会按照一定规则被存储在同一个桶中。通常情况下,在哈希冲突发生时,新的键值对会被插入到链表的头部。

============================================================
文字描述可能一看就头大,我来举一个例子解释数组与桶是如何成为HashMap的组成部分的

假设我们有一个 HashMap,并设置初始容量为 4,并插入以下三个键值对:

键:“sky”,值:“blue”
键:“grass”,值:“green”
键:“sun”,值:“orange”
首先,根据键的哈希码计算它们的索引位置。假设这三个键的哈希码分别为:

“sky” 的哈希码:123
“grass” 的哈希码:456
“sun” 的哈希码:789
根据初始容量 4 和哈希码的计算,我们可以得到它们的索引位置:

“sky” 的索引位置:123 % 4 = 3
“grass” 的索引位置:456 % 4 = 0
“sun” 的索引位置:789 % 4 = 1
然后,我们将键值对插入到相应的桶中:

这里的桶就是指数组元素

在索引位置 3 的桶中插入键值对 (“sky”, “blue”)
桶 3:[(“sky”, “blue”)]

在索引位置 0 的桶中插入键值对 (“grass”, “green”)
桶 0:[(“grass”, “green”)]

在索引位置 1 的桶中插入键值对 (“sun”, “orange”)
桶 1:[(“sun”, “orange”)]

最终,HashMap 的内部结构如下所示:
Alt

当然这只是一个简单的示例,当链表长度达到一定值(默认为 8)时,链表可能会被转换成红黑树以提高查询效率。这种转换过程使得实际的桶结构更为复杂,但基本原理仍然是通过数组和桶的组合来实现哈希表。

补充知识:
hashmap的初始容量是16,在第一次put的时候进行的扩容初始化,链表长度大于8时才会转换为红黑树,红黑树长度小于6时会退化为链表,扩容因子(就是loadFactor)是0.75,初始化扩容阈值为大于12。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值