HashMap 原理及常见面试题
之前有面试问道hashMap 的问题,感觉又熟悉又陌生,今天重新查看源码把问题记录下(本文基于jdk1.8进行分析)
1、问题一:hashMap的底层实现?
首先HashMap内部有一个叫做Node的静态内部类,每个Node 存有hash值,key,value,和指向下一个Node的指针(链表结构)
整体上可以猜测每一个node会维护一个链表来存储
然后再看HashMap&put 方法
所以基本上hashMap的一个结构如下:
数组下表是由 hash & lengh - 1 决定的
所以hashMap是由 数组+链表+红黑树实现的
2、问题二:HashMap hash冲突是怎么解决的?
这个问题之前hashmap没有引入红黑树的时候, hash & lengh - 1 算出的index相同使用的是链表的单链表的形式,相同的散列值由头指向尾查找最后能添加的位置进行插入,
这样导致的问题是每次冲突了算法复杂度o(n),jdk1.8中将大于8的单链表转化成红黑树进行存储,使得插入和查找最大复杂度为 o(logn)
3、问题三:红黑树的插入算法?
满足5个条件的树叫做红黑树
a、任何一个节点要么是红要么是黑
b、根节点是黑
c、叶子节点是黑(叶结点即指树尾端NIL指针或NULL结点)
d、如果一个结点是红的,那么它的两个儿子都是黑的。
e、对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。
插入的算法如下:
i、将插入的节点置为红
ii、插入的父节点为空树,直接将插入节点置黑
iii、插入的父节点为黑,直接插入节点
iiii、插入的父节点为红,叔节点为红色,将当前节点的父节点和叔叔节点涂黑,祖父结点涂红,把当前结点指向祖父节点
iiii、插入的父节点为红,叔叔节点为黑,当前节点是其父节点的右子节点,当前节点的父节点做为新的当前节点,以新当前节点为支点左旋
iiiii、插入的父节点为红,叔叔节点为黑,当前节点是其父节点的左子节点,父节点变为黑色,祖父节点变为红色,在祖父节点为支点右旋
上面是红黑树插入的算法,
hashmap里面红黑树具体代码是从根节点往后查找,插入的hash值小于节点,取left子节点,反之取right子节点直到叶子节点进行插入
红黑树插入实现代码
4、问题4:hashmap的扩容算法是怎样的?
5、问题5 hashmap 为什么使用红黑树优化hash冲突而不是用查找树?
查找树是一种任何左子树比父亲节点小,右子树比父亲节点大的树,查找时可以使用二分法来进行查找,最好的情况是
事件复杂度 o(logn),但是查找树如果只有左子树,或者只有右子树的情况就会退化成为一个链表
这种情况下的查找复杂度在 o(logn)~o(n)之间,而红黑树的效率是o(logn),所以使用红黑树更好
6、为什么不适用平衡树来代替红黑树呢?
平衡树是从查找树变化来的 每个节点的左子树和右子树的高度差至多等于1,这个条件过于苛刻,基本每次插入都需要通过左旋或者右旋进行调整树的结构效率太低,虽然平衡树的查找效率是o(logn)
7、HashMap中hash函数怎么实现的?
hashcode的高16位不变,低16位变成(高十六位^低十六位),这个得到的hash&(length-1) 便得到了数组下标
这么做是为了提高取模效率
具体效果参考网站: http://rbtree.phpisfuture.com/
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战