hashmap put过程_Java 面试经典之 HashMap 原理

介绍

在你的工作面试中,这个问题被问了多少次?对我来说超过 10 次,我想把这个问题说得非常清楚,以节省每个人的时间。

HashMap 如何在 Java 中工作

HashMap 是一个基于散列表的键值对容器。它通常充当一个二进制哈希表,但是当 bins 变得太大时,它们就会被转换成 TreeNodes 的 bins。

一个典型的 HashMap 看起来是这样的:

b329e3aada7ef441d36a2199cc8cb0bf.png

哈希表

该表充当索引,在第一次使用时初始化,例如 put(key, value)。默认容量为16。 假设我们初始化了一个 map:Map map = new HashMap<>(),我们现在想要 map.put(user1, "emai-add"),首先要识别表中的位置。Node 应该放在哪个单元格?

在哈希表中标识索引

11e044caad5de87fa9cd68ad1184b39f.png

在 Java 1.8 的实现中,是通过 hashCode() 的高 16 位异或低 16 位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在 bucket 的 n 比较小的时候,也能保证考虑到高低 bit 都参与到 hash 的计算中,同时不会有太大的开销。

4c88b74f15b98a669a030ac50a83e0a2.png

节点

如果 table[index] 为空,我们可以直接 put 一个 Node(key, value) ,例如:

881afbd0518535d4387d950adea71bdb.png

如果单元格已经被占用,检查节点并更新/插入新节点:

af37e2528c2c853b62bef002938533f6.png

节点 Node 现在附加到哈希表上了。

在 put 方法的末尾,HashMap 将检查是否需要 resize()。

必要时调整大小

当put时,如果发现目前的 bucket 占用程度已经超过了 Load Factor 所希望的比例,那么就会发生 resize。在 resize 的过程,简单的说就是把 bucket 扩充为 2 倍,之后重新计算 index,把节点再放到新的 bucket 中。resize 的注释是这样描述的:

Initializes or doubles table size. If null, allocates in accord with initial capacity target held in field threshold. Otherwise, because we are using power-of-two expansion, the elements from each bin must either stay at same index, or move with a power of two offset in the new table.

大致意思就是说,当超过限制的时候会 resize,然而又因为我们使用的是 2 次幂的扩展(指长度扩为原来 2 倍),所以,元素的位置要么是在原位置,要么是在原位置再移动 2 次幂的位置。

923ccbb8d9bb4073a89bc46009199886.png
d853236faf6b9527e11a4671331e83d6.png

如果超过了负载因子(默认0.75),则会重新 resize 一个原来长度两倍的 HashMap,并且重新调用 hash 方法。

感谢大家的观看,欢迎关注我的头条号。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值