大型互联网公司跳槽必备之HashMap原理解析

初级面试题

  1. JDK8中的HashMap有哪些改动?
  2. JDK8中为什么要使用红黑树?
  3. 为什么重写对象的Equals方法时,要重写HashCode方法,跟HashMap有关系吗?为什么?
  4. HashMap是线程安全的吗?遇到过ConcurrentModificationException异常吗?为什么会出现?如何解
    决?
  5. 在使用HashMap的过程中我们应该注意些什么问题?

高级面试题

  1. 笔试中要求你手写HashMap?
  2. 你知道HashMap的工作原理吗?
  3. HashMap中 能PUT两个相同的Key吗?为什么能或为什么不能?
  4. HashMap中的键值可以为NULL吗?能简单说一下原理吗?
  5. HashMap扩 容机制是怎么样的,JDK7与 JDK8有什么不同吗?

JDK8中的HashMap有哪些改动?

  1. JDK7中的底层实现是数组+链表,JDK8中使用的是数组+链表+红黑树。
  2. JDK7中扩容时有可能出现死锁,JDK8中 通过算法优化不会出现死锁了。
  3. JDK8中对算哈希值的哈希算法进行了简化以提高运算效率。

JDK8中为什么要使用红黑树?

因为JDK7中是用数组+链表来作为底层的数据结构的,但是如果数据量较多,或者hash算法的散列性不够,可能导致链表上的数据太多,导致链表过长,考虑-种极端情况:如果hash算法很差,所有的元素都在同一个链表上。

那么在查询数据的时候的时间复杂度和链表查询的时间复杂度差不多是一样的,我们知道链表的一个优点是插入快,但是查询慢,所以如果HashMap中出现了很长的链表结构会影响整个HashMap的查询效率,我们使用HashMap时插入和查询的效率是都要具备的,而红黑树的插入和查询效率处于完全平衡二叉树和链表之间,所以使用红黑树是比较合适的。

HashMap扩容机制是怎么样的,JDK7 与JDK8有什么不同吗?

首先,我们需要知道HashMap为什么需要扩容,道理很简单,HashMap底层 是用数组+链表实现的,而数组是预先就已经分配好内存的,如果需要对数组进行扩容,需要重新开辟-个新的数组再将旧数组上的元素进行转移,如果不进行扩容,那么会导致HashMap的链表过长,查询效率降低,所以需要对数组进行扩容。

在JDK7中,HashMap扩 容的条件是(size >= threshold) && (nu1l 1=table[ bucketIndex] )。
size为HashMap当前的容量,threshold 初始化值为12, table[bucketIndex ]代表所put进来的key所对应的数组上的元素,所以在JDK7中扩容条件是当Put操作传入的Key值所对应的数组位置上不为空时并且当前容量大于等于了扩容的阈值时才进行扩容,JDK7中的扩容思路是:开辟一个新的数组,数组大小为原数组的两倍,然后再将数组上的链表与元素转移到新数组上,此过程可能会出现死锁

JDK8中的扩容条件比JDK7中要少,只有当前容量大于等于了扩容的阈值时才进行扩容,并且扩容的思路也发生了变化,思路比较复杂具体看本视频内容的讲解。

为什么重写对象的Equals方法时,要重写HashCode方法,跟HashMap有关系吗? 为什么?

跟HashMap有关系,或者说因为HashMap中用到了对象的hashcode方法所以会有关系,因为我们如果在设计两个对象相等的逻辑时,如果只重写Equals方法,那么-个类有两个对象A1, A2, 他们的A1.equals(A2)为true, A1.hashcode和A2 .hashcode不- -样。

当将A1和A2都作为HashMap的key时,HashMap会认为它两不相等,因为HashMap在判断key值相不相等时会判断key的hashcode是不是一样,hashcode- 样相等,所以在这种场景下会出现我们认为这两个对象相等,但是hashmap不这么认为,所以会有问题。

HashMap是线程安全的吗?遇到过ConcurrentModificationException异常吗?为什么会出现?如何解决?

HashMap不是线程安全的,ConcurrentModificationException这 个异常通常会出现在多线程环境中,比如两个线程共享一个hashmap, -个线程在遍历,-个线程在删除,那么就有可能出现ConcurrentModificationException异常。

假设如果不出现这个异常,那么则可能出现并发问题,可能遍历的线程发现hashmap存的元素少了, HashMap为 了防止这种情况出现,所以直接会抛出ConcurrentModificationException异常,这是Fast-Fail机制, 让错误尽快出现,不让用户继续“错下去”。具体.的原因需要参考源码实现,想了解的同学也可以参看教学视频的讲解。

在使用HashMap的过程中我们应该注意些什么问题?

  1. HashMap的扩容机制是很影响效率的,所以如果事先能确定有多少个元素需要存储,那么建议在初始
    化HashMap时对数组的容量也进行初始化,防止扩容。
  2. HashMap中使用了对象的hashcode方法,而且很关键,所以再重写对象的equals时建议-定要重写
    hashcode方法。
  3. 如果是用对象作为HashMap的key,那么请将对象设置为final,以防止对象被重新赋值,因为一旦重新
    赋值其实就代表了-个新对象作为了key,因为两个对象的hashcode可能不同。
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值