Java面试题———集合篇②

目录

一,HashMap是怎么解决哈希冲突的

二,HashMap的扩容机制是怎样的

三,为何HashMap的数组长度一定是2的次幂?

四,说一下HashSet的实现原理?

五,HashSet如何检查重复?


一,HashMap是怎么解决哈希冲突的?

首先,HashMap的底层有一个数组,它在保存元素的时候,会对元素的key进行hash运算,得到hash值,然后再使用hash值对数组长度取余,得到元素在数组中的位置,这样的话,不同的元素计算完毕之后,就可能会被分配到数组中的同一个位置上,这就是所谓的哈希冲突。

解决hash冲突最常用的方式有链表法和开放地址法,而HashMap就是采用了链表法。具体做法就是当哈希冲突出现之后,HashMap会在发生冲突的位置上创建一个链表来保存元素,当然在JDK1.8之后,又对此做出了改进,那就是当链表的长度>8,并且数组长度>=64的时候,链表就会转换为红黑树,使得效率更高。

二,HashMap的扩容机制是怎样的?

HashMap的扩容机制是指当HashMap中的元素个数超过数组长度乘以负载因子时,就会重新分配一个更大的数组,并将原来的元素重新计算哈希值并插入到新的数组中。

在JDK1.8中,底层是调用resize方法实现扩容的,它的默认做法是:当元素个数超过数组长度的0.75倍时触发扩容,每次扩容的时候,都是扩容为原来的2倍, 扩展后Node对象的位置要么在原位置,要么移动到原偏移量两倍的位置。

三,为何HashMap的数组长度一定是2的次幂?

  1. 计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模

  2. 扩容时重新计算索引效率更高: hash & oldCap == 0 的元素留在原来位置 ,否则新位置 = 旧位置 + oldCap

  3. 为了能让 HashMap 存数据和取数据的效率高,尽可能地减少 hash 值的碰撞,也就是说尽量把数据能均匀的分配,每个链表或者红黑树长度尽量相等。我们首先可能会想到%取模的操作来实现。

四,说一下HashSet的实现原理?

        HashSet是基于HashMap实现的,HashSet的值存放于HashMap的key上,HashMap的value统一为present,因此 HashSet的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,由于HashMap的键是不能重复的,所有HashSet 不允许重复的值。

五,HashSet如何检查重复?

        HashSet是一个不允许存储重复元素的集合,它通过哈希表来实现。在HashSet中,每个元素都是唯一的,如果尝试添加一个已经存在的元素,HashSet会拒绝并保留原有的元素。

具体做法是在向HashSet中保存元素的时候,会先计算该元素的哈希值,然后确定这元素在数组中的位置,如果该位置上没有元素,则保存成功,如果有元素,则调用equals方法去跟存在的每个值进行比较,表较结果有一个相等,则直接丢弃;不相等,就会被挂在老元素的后面。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啵啵薯条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值