HashMap相关面试题

这一段时间学习HashMap原理再根据相关资料提出的一些问题,进行的解答

推荐一篇文章:https://crossoverjie.top/2018/07/23/java-senior/ConcurrentHashMap/

 

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) && (null 1= table[bucketlndex]) , size 为HashMap当 前的容置,threshold初始化值为12, table[bucJcetIndejc]代表所put进来的key所对应的数组上的元素,所以在JDK7中扩容条件是当Put操作传入的Key值所对应的数组位霣上不为空时并且当前容量大于等于了扩容的阈值时才进行扩容,JDK7中的扩容 思路是:开辟一个新的数组,数组大小为原数组的两倍,然后再将数组上的链表与元素转移到新数组上,此过程可能会出现死锁,具体可参考:http://www.importnew.com/22011.html

     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是线程安全的吗?遇到过ConcurrentModificationExceotion异常吗?为什么会出现?如何解决?

    HashMap不是县城安全的,ConcurrentModificationException这个异常通常会出现在多线程环境中,比如两个线程共享一个hashmap,一个线程在遍历,一个线程再删除,那么就会出现这个异常,假设如果不出现这个异常,那么则可能出现并发问题,可能遍历的线程发现hashmap存的元素少了,HashMap为了防止这种情况出现,所以会直接跑出了ConcurrentModificationException异常,这是Fast-Fail机制,让错误尽快出现,不让用户继续错下去。

    解决方法有使用HashMap. iterator()进行迭代,使用iterator.remove进行删除,或者直接使用ConcurrentHashMap进行数据处理

 

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值