【HashMap】知识点归纳、HashMap面试题总结

此篇文章为HashMap常见知识点归纳及面试题总结。
	想了解从源码过程分析,可以看我的另一篇文章:↓  一步步从源码分析,通俗易懂!

JDK1.7: 【HashMap-1.7】-从源码解析-通俗易懂【扩容】【线程不安全】【put&get原理】【遍历删除】.


总结

针对Jdk7

HashMap的默认长度是多少?

调用无参构造,默认长度为16

HashMap为什么Key可为空?

put方法校验当key为null 时,会将元素存储到 table[0] 的位置上

HashMap的数据结构与底层原理?

1.7 采用数组 + 链表 
当 key 冲突时 ,会形成链表
【拓展】关于1.8 后续会出文章详解
1.8 采用 数组 + 链表 + 红黑树 
当碰撞时 形成链表,当链表长度大于TREEIFY THRESHOLD会形成红黑树

HashMap计算索引为什么是h & (length-1) ?

由于底层存放的是entry数组结构,计算索引时,要使得 取值范围刚好在 0 ~ 数组长度-1 的范围内。
第一想法可能是想到 用 取模 运算 h % length ? 不是相同的结果么?
不用取模运算 是因为 取模运算是 是 进行一步一步的除法,得到最终的余数。
计算机在二进制位运算 时的效率 要远大于 取模运算的。

HashMap的长度为什么要取2的次幂?

如果不采取2的次幂值,当进行put时,计算索引 " h & (length-1) " 时,转换为二进制位运算 最后一位 为0 ,
会大大增加不同hash值 计算索引值相同的几率,从而倒置碰撞的几率增大。
 
例如 key ="LL" hahs="2315"  按位与计算 转化为二进制 
当前  length = 15  的话
	h & (length-1) = h & 14
	h 1001 0000 1011
      0000 0000 1110
   =  0000 0000 1010
   =  10
   
   假如 hash="2314"
	h & (length-1) = h & 14
    h 1001 0000 1010
      0000 0000 1110
   =  0000 0000 1010
   =  10
不同的h值计算的索引一致

HashMap是线程安全的么?为什么?

不是线程安全的。
多线程在扩容时容易产生循环链表情况,当下次get到当前位置上时,会造成死循环!
原因是:
由于在hashMap 在扩容时 会将原数组上的值 转移到 扩容后的数组上,采用头插法。
会产生链表元素倒置情况。
若两个线程都进行扩容,进行完 Entry<K,V> next = e.next;该操作时,线程2挂起。
线程1执行完transfer方法后,线程2继续执行,由于已经存储了 数组开始时的引用,
在转移元素时会产生循环链表情况。【具体过程 可看上面扩容过程】
在调用get方法时,key匹配到产生循环链表上时,会产生死循环。

线程安全的Map有哪些?

我们会想到 
HashTable 
  是因为 hashTable 在 put、get、size、remove 等等方法上 加上了synchronized 简单粗暴 保证了线程同步。
  因为是 直接 synchronized  加在 方法上  效率受很大影响
ConcurrentHashMap 
 底层采用分段的数组 + 链表实现 只锁住当前段,效率较高

HashMap为什么在1.8中引用了红黑树?

1.7 采用数组 + 链表 
当 key 冲突时 ,会形成链表
【拓展】关于1.8 后续会出文章详解
1.8 采用 数组 + 链表 + 红黑树 
当碰撞时 形成链表,当链表长度大于TREEIFY THRESHOLD会转化为红黑树
因为:
	如果采用数组 + 链表的形式,当元素达到一定量的时候,并且key冲突的元素过多时,会导致链表过长。
	我们都知道,链表结构的缺点 遍历查找时 大大降低了效率。

以上内容,若有不足或错误,还望指正。

不止于前 未来可期 ···

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值