记一次HashMap面试

从网上已经身边同事朋友的面试情况来看,面试HashMap几乎是必问的,网上也很多类似的文章,但是真面起来,发现还是有很多点可以深抠的。本篇就结合一次面试经历说一下之前没有注意的点吧。

HashMap的底层结构

这个相信不用我多说,大家都知道HashMap的底层是Node数组结构Node<K,V>[] table

扩容也不用我多说了,在size达到阈值(默认0.75的负载因子*容量)时触发扩容。

数组的capacity大小是2的x幂也无需多言,但这里多问一句为什么是2的x幂而不是其他数呢?我们知道,当一个key被放进到数组时需要明确自己被放在哪个位置。最简单的当然就是对key进行hash之后h%n确定。而如果数组的长度n是2的x幂,h%n这个操作与h&(n-1)是等价的,会更快。同时在扩容时,每个key需要重新确定自己在数组中的index,这时如果数组每个位置的元素都变了一次,显然开销会比较大。但是如果n是2的x幂,那么在扩容变成2n后需要重新确认index时,对某个table[index]这个元素的新位置只有两种可能:1. 在原地不动(如果h&n的高位为0),2. index+nh&n的高位为1)。这样每个元素移动的概率只有50%,显然会节约很多拷贝操作。

HashMap中链表转红黑树

这个也是高频问点,大家也基本都清楚,JDK1.8之后,如果某位置的链表长度大于某个阈值之后,就会转为红黑树,防止链表深度过大,从而查询时复杂度达到o(n)最坏情况。但是细问起来,如果没有认真看过putVal方法中每一行代码,真的有的地方可能会忽略。比如:

  1. 链表长度达到多少之后开始转链表?你可能脱口而出8。但真的超过这个阈值8之后就会转树吗?我们跟进代码后会发现:还有另一个条件,即数组的长度如果小于MIN_TREEIFY_CAPACITY默认64这个值,会触发一次扩容而并不会执行转树操作,所以链表的长度是可以超过8的。
final void treeifyBin(Node<K,V>[] tab, int hash) {
int n, index; Node<K,V> e;
if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
resize();
else if ((e = tab[index = (n - 1) & hash]) != null) {
TreeNode<K,V> hd = null, tl = null;
do {
TreeNode<K,V> p = replacementTreeNode(e, null);
if (tl == null)
hd = p;
else {
p.prev = tl;
tl.next = p;
}
tl = p;
} while ((e = e.next) != null);
if ((tab[index] = hd) != null)
hd.treeify(tab);
}
}
  1. 在转成红黑树时,每个key应该放在左子树还是右子树?这个由什么确定?因为HashMapkey并不要求是Comparable,而TreeMap很显然key是要满足Comparable的,那么此时新来一个TreeNode,左右确定以什么为依据呢?

    面试时在次数被面试官坑了一把,其实我们仔细想想,我们并不需要严格的确定某个TreeNode应该挂在它父节点的左边还是右边,挂在哪边都可以啊,只要我插入时按某个标准,查找时也按同样的标准,两者保持一致就可以了,对吧?跟到源代码,对于没有实现Comparablekey,比较一下hashCode就可以了。源码中的比较一句就是两个keyhashCode,使用的是System.identityHashCode(object)这个native方法。
        static int tieBreakOrder(Object a, Object b) {
int d;
if (a == null || b == null ||
(d = a.getClass().getName().
compareTo(b.getClass().getName())) == 0)
d = (System.identityHashCode(a) <= System.identityHashCode(b) ?
-1 : 1);
return d;
}

后记

还有大家都耳熟能详的东西我就不赘述了,面后也思考了一下,基础还是很重要,还是有很多指的深入思考的地方,一定要打牢基础,可能准备了很多框架原理实践什么的,如果基础的没答好,这些应用层的东西准备的再好,可能也没机会跟面试官聊了,当然在面试中如何去引导面试官这一点也很重要,俗话说的好,把对方拉倒跟我一个低智商区,然后用我丰富的经验打败他,这一点很重要,以后要多注意。

记一次HashMap面试的更多相关文章

  1. 从HashMap面试聊聊互联网内卷

    微信公众号:大黄奔跑 关注我,可了解更多有趣的面试相关问题. 写在之前 毫无疑问,回想2020年有什么词出现在眼前最多的,无疑是"996"和"内卷",从马老师的 ...

  2. 有关 HashMap 面试会问的一切

    前言 HashMap 是无论在工作还是面试中都非常常见常考的数据结构. 比如 Leetcode 第一题 Two Sum 的某种变种的最优解就是需要用到 HashMap 的,高频考题 LRU Cache ...

  3. 一万三千字的HashMap面试必问知识点详解

    目录 概论 Hasmap 的继承关系 hashmap 的原理 解决Hash冲突的方法 开放定址法 再哈希法 链地址法 建立公共溢出区 hashmap 最终的形态 Hashmap 的返回值 HashMa ...

  4. 对于大学4年的反思(续),记我的ThoughtWorks面试

    之前我写了一篇对于大学四年的反思,时隔一个月,为什么我这么快就要来写这篇续章呢?主要有两个原因,第一是感谢静子姐姐,记得知乎上有个回答里面说过人生需要有贵人的帮助,遇到贵人是一件很幸运的事情.我想,静 ...

  5. Java Web架构知识整理——记一次阿里面试经历

    惭愧,从一次电面说起.我个人在某国企做一名软件设计师,国企大家都懂的,待遇一般而且没啥意思,做的方向基本都是操作系统.驱动和工具软件的开发,语言基本都是C/C++.最近也想跳槽,刚好有幸得到了一次阿里 ...

  6. HashMap面试知识点

    HashMap的工作原理是近年来常见的Java面试题. 几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如 ...

  7. 你不得不知道的HashMap面试连环炮

    为什么用HashMap? 简述一下Map类继承关系? 解决哈希冲突的方法? 为什么HashMap线程不安全? resize机制? HashMap的工作原理是什么? 有什么方法可以减少碰撞? HashM ...

  8. 记一次Java面试问题点总结

    引言 昨日接了一个阿里外包的电话面试,问了一些技术问题感觉到自己是真的菜,接触Java开发已经也有一段时间,技术方面说来惭愧,一直以来只是局限于框架工具的用法,也没有进行了解其实现的原理,更重要的是一 ...

  9. HashMap面试知识点总结

    主要参考 JavaGuide 和 敖丙 的文章, 其中也有参考其他的文章, 但忘记保存链接了, 文中图片也是引用别的大佬的, 请见谅. 新手上路, 若有问题, 欢迎指正. 背景 HashMap 的相关 ...

随机推荐

  1. Linux内核设计与实现 第十八章

    1. 内核调试的难点 重现bug困难 调试风险比较大 定位bug的初始版本困难 2. 内核调试的工具和方法 2.1 输出 LOG 输出LOG不光是内核调试, 即使是在用户态程序的调试中, 也是经常使用 ...

  2. DataGridView不显示未绑定的列-AutoGenerateColumns

    DataGridView绑定数据源时,会自动显示未绑定的列,怎么让其不显示未绑定的列呢? 设置AutoGenerateColumns属性即可 this.dataGridView1.AutoGenera ...

  3. T检验在项目上的具体实施

    我觉得 T 检验,应该用在 判断某种仿真条件因素 对碳纳米管的随机性 是否有显著影响 上.所以不是针对<相同仿真条件对不同源的影响>这个表中的数据做 T 检验 如:判断 金属/半导体比率 ...

  4. vis.js绘图库的一个BUG以及源码修正

    1. BUG 1.1 BUG触发情况 在使用vis.js绘图时,加入两个节点A和B之间既存在一条从A指向B的边,同时也存在一条从B指向A的边,那么这个绘图库就会崩溃. 1.2 BUG解析 vis.js ...

  5. [2017BUAA软工]结对项目-数独程序扩展

    零.github地址 GitHub地址:https://github.com/Liu-SD/SudoCmd (这个地址是命令行模式数独的仓库,包含了用作测试的BIN.DLL核心计算模块地址是:http ...

  6. Tether USDT 节点钱包的安装与使用-omni layer

    1 什么是Omni Layer Omni Layer是一种通信协议,它使用比特币区块链实现智能合约,用户货币和分散式点对点交换等功能. Omni Core是基于比特币核心代码库的快速,便携式Omni层 ...

  7. Ryuji doesn't want to study 2018 徐州赛区网络预赛

    题意: 1.区间求 a[l]×L+a[l+1]×(L−1)+⋯+a[r−1]×2+a[r](L is the length of [ l, r ] that equals to r - l + 1) ...

  8. MT【110】巧设法向量解决距离问题

    分析:设面的法向量$n=(x,y,z)$

  9. Django入门项目实践(下)

    5.设置应用程序的样式 安装django-bootstrap3. # untitled/untitled/settings.py # ··· INSTALLED_APPS = [ 'django.co ...

  10. 基于CMS的组件复用实践

    目前前端项目大多基于Vue.React.Angular等框架来实现,这一类框架都有一个明显的特点:基于模块化以及组件化思维.所以,开发者在使用上述框架时,实际上是在写一个一个的组件,并且组件与组件之间 ...