HashMap面试常问

HashMap面试题常问:

hashMap和hashTable

线程不安全效率高 和 线程安全效率低
Key和Value都可以为null,hashTable,Key 和 Value都不允许null

HashMapHashTable
线程不安全效率高线程安全效率低
Key / Value都可以为 nullKey / Value都不可以为 null
默认容量16默认容量11
put 时才初始化 table构造函数时就初始化table
2倍扩容2倍+1扩容

hash算法区别:
HashMap:
hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16)
index = hash & table.length-1

HashTable: index = (e.hash & 0x7FFFFFFF) % Capacity;


为什么哈希数组(table)的长度必须是2 的 n 次幂?

解析:因为方便我们计算索引的位置!key通过一系列计算最后在哈希数组中确定索引的位置。怎么确定?如果我们把 key 看作数字(例如 7)我们把这个数字对数组长度(例如初始值 16)进行取余,我们就确定了这个元素所对应的位置。但是我们在put源码里我们会发现,我们获得key对象的地址之后,我们进行的操作是这个数字 和 数组长度-1 与操作。经过验证,我们会发现这两个操作的结果是一摸一样的!为了取余更快,数字和长度-1进行与操作的核心原因,就是要让除第一位外,余下的数字全为1。
其次方便我们再扩容是快速填充元素,如果第一次初始化的值是16,那么resize时,我们就对比key地址的二进制位的第5位,如果第五位尾0,那么就放在原来的位置,如果为1,就放在原来的索引+原来的哈希数组长度 的位置。

总结:
一:因为长度为2的n次幂方便key的值做与运算,与运算的本质是为了内存地址取余长度,而与运算的速度比取余快非常多。
二:扩容是设计到元素的迁移,只需要判断之前二进制的前一位即可,如果为0,位置不变,如果为1 ,位置为 旧位置+旧长度。

在这里插入图片描述


LinkedHashMap,TreeHashMap:

LinkedHashMap:底层用链表实现,是有序的集合(按照插入顺序)

TreeMap:底层用红黑树实现,也是有序的集合(按自然顺序,例如,字符按照a,b,c,d,数字按照1,2,3,4)


key为null时,这次put操作,将被放入哪一个位置?为什么?

答:数组0号桶,因为hash函数在执行时,当 key 为null时返回的是0。


HashMap中的哈希数组(table)什么时候初始化,初始化大小有哪几种情况

table 在 put 时调用resize()进行初始化,初始化大小除非我们在调用构造器时,给定参数,其余情况全部都是默认初始容量8,并且给定的大小也会变成 2 的 n 次幂。


HashMap为什么要扩容?谈谈你的理解

hashMap最重要的就是查找和添加数据的效率,如果在同一个位置例如 0 号下标,存储了1000组数据,那么查找的效率会非常慢,效率会直接退化为链表查找或者红黑树查找。所以当数据到了阈值(threshold)时,我们就需要新的空间去存放一部分数据,这样就使当前位置的查找和添加数据的效率变高。


HashMap扩容算法,描述一下。

扩容算法是resize()方法,在这个方法中我们先判断 table 是否为 null,如果为null就初始化。之后我们要对table进行2倍扩容,同时阈值(threshold)也要进行重新赋值。在resize()时,重新放置数据,首先遍历此下标的数据,如果是红黑树就是红黑树遍历处理;如果是链表,将高位为0的,就放入loHead 链表,高位为1的就放入newHead链表,举个例子,当 table 大小为 16 时,我们只需要判断 key 的hash值的后4位相同即可,当时当扩容之后大小变成32,我们就需要判断后5位,但是现在我们只需要判断第5位即可,第5位为0,那么放入loHead链表,为 1 就放入newHead。而新位置,就是 旧位置+旧长度。最后我们只需要将loHead放入旧位置,newHead放入新位置即可。


HashMap存放的 Node 节点中 hash 是否与你 key 的hashcode一致?

不一致,首先Key的hashCode,是key的内存地址!而hash,是hashCode对table长度-1进行取余运算。当key为null时,hash为0。


为什么JDK1.8中引入红黑树?谈谈你理解

参考文章:HashMap在jdk1.8为何引入了红黑树?
因为如果数据量实在过大,链在同一个位置的数据就会非常的多,查找的效率就会退化成链表 O(n)。而引入了红黑树之后,红黑树本质上是一个二叉树,而且根据红黑树的性质,采用的是二分查找,所以红黑树查找的时间复杂度是O(log n) 这无疑将查找的速率大大加快。所以JDK1.8引入了红黑树。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值