HashMap的相关面试题

哈希表的理解

哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表或哈希表

JDK8中HashMap为什么到8转为红黑树 到6转为链表?

TreeNode(红黑树中)占用空间是普通Node(链表中)的两倍,为了时间和空间的权衡。
如果是7,那么在极端情况下比如在同一个哈希桶中,对长度为8的哈希桶进行频繁的删除和插入,会频繁的 树化<=>非树化。

HashMap的初始大小为什么是16?加载因子为什么是0.75?扩容倍数为什么是2?扩容策略?

HashMap的初始大小为什么是16?
确定桶下标的最后一步是将 key 的 hash 值对桶个数取模:hash%capacity,如果能保证 capacity 为 2 的 n 次方,那么就可以将这个操作转换为位运算。位运算的代价比求模运算小的多,因此在进行这种计算时用位运算的话能带来更高的性能。16=2^4,不至于过大也不至于过小。

加载因子为什么是0.75?
提高空间利用率和 减少查询成本的折中,主要是泊松分布,0.75的话碰撞最小。加载因子过高,提高了空间利用率,但同时也增加了查询时间成本;加载因子过低,虽然可以减少查询时间成本,但是空间利用率很低。

扩容倍数为什么是2?
HashMap的初始容量是2的n次幂,扩容也是2倍的形式进行扩容,是因为容量是2的n次幂,可以使得添加的元素均匀分布在HashMap中的数组上,减少hash碰撞,避免形成链表的结构让查询效率降低!

扩容策略?
JDK7中会重新计算hash,JDK8中不需要重新计算hash,只需要看原来新增的那个hash值新增的那个bit位是0还是1,是0的话索引不变,是1的话索引变成"原索引+oldCap"
在这里插入图片描述

hashMap插入数据的过程

在这里插入图片描述
1.首先判断是否进行了初始化,如果没有则进行resize();
2.通过传入键值对里面的key获取hashcode和容量,通过hash()方法得到数组下标,然后通过该下标获取该哈希桶的头节点;
3.如果没有发生哈希碰撞(头节点为null),直接进行插入操作;
4.如果发生哈希碰撞(头节点不为null),分为两种情况:
(1) 与桶内某个元素equals(),返回true就覆盖;
(2)与桶内所有元素都不相等,执行插入操作,可能是链表或者红黑树;
5.链表新增操作后,会有两个判断:
(1) 哈希桶是单链表结构,桶内数量达到8并且元素数量大于等于64,会转为红黑树;
(2)元素数量达到容量的0.75,则进行resize();

在这里插入图片描述

hashMap获取数据的过程

1.调用key的hashcode方法,根据返回值定位到数组下标;
2.判断该数组下标对应的头节点是否为null,如果为null,则返回null;
3.如果头节点不为null,首先判断是不是红黑树,如果是,则调用红黑树的方法,否则遍历链表,比较每个元素的key,调用key的equals()与被查询的key比较,相等就返回该key对应的value;遍历完链表都没有相等的就返回null;
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值