记一次HashMap面试
记一次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+n(h&n的高位为1)。这样每个元素移动的概率只有50%,显然会节约很多拷贝操作。
HashMap中链表转红黑树
这个也是高频问点,大家也基本都清楚,JDK1.8之后,如果某位置的链表长度大于某个阈值之后,就会转为红黑树,防止链表深度过大,从而查询时复杂度达到o(n)最坏情况。但是细问起来,如果没有认真看过putVal方法中每一行代码,真的有的地方可能会忽略。比如:
- 链表长度达到多少之后开始转链表?你可能脱口而出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);
}
}
- 在转成红黑树时,每个
key应该放在左子树还是右子树?这个由什么确定?因为HashMap的key并不要求是Comparable,而TreeMap很显然key是要满足Comparable的,那么此时新来一个TreeNode,左右确定以什么为依据呢?
面试时在次数被面试官坑了一把,其实我们仔细想想,我们并不需要严格的确定某个TreeNode应该挂在它父节点的左边还是右边,挂在哪边都可以啊,只要我插入时按某个标准,查找时也按同样的标准,两者保持一致就可以了,对吧?跟到源代码,对于没有实现Comparable的key,比较一下hashCode就可以了。源码中的比较一句就是两个key的hashCode,使用的是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面试的更多相关文章
- 从HashMap面试聊聊互联网内卷
微信公众号:大黄奔跑 关注我,可了解更多有趣的面试相关问题. 写在之前 毫无疑问,回想2020年有什么词出现在眼前最多的,无疑是"996"和"内卷",从马老师的 ...
- 有关 HashMap 面试会问的一切
前言 HashMap 是无论在工作还是面试中都非常常见常考的数据结构. 比如 Leetcode 第一题 Two Sum 的某种变种的最优解就是需要用到 HashMap 的,高频考题 LRU Cache ...
- 一万三千字的HashMap面试必问知识点详解
目录 概论 Hasmap 的继承关系 hashmap 的原理 解决Hash冲突的方法 开放定址法 再哈希法 链地址法 建立公共溢出区 hashmap 最终的形态 Hashmap 的返回值 HashMa ...
- 对于大学4年的反思(续),记我的ThoughtWorks面试
之前我写了一篇对于大学四年的反思,时隔一个月,为什么我这么快就要来写这篇续章呢?主要有两个原因,第一是感谢静子姐姐,记得知乎上有个回答里面说过人生需要有贵人的帮助,遇到贵人是一件很幸运的事情.我想,静 ...
- Java Web架构知识整理——记一次阿里面试经历
惭愧,从一次电面说起.我个人在某国企做一名软件设计师,国企大家都懂的,待遇一般而且没啥意思,做的方向基本都是操作系统.驱动和工具软件的开发,语言基本都是C/C++.最近也想跳槽,刚好有幸得到了一次阿里 ...
- HashMap面试知识点
HashMap的工作原理是近年来常见的Java面试题. 几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道Hashtable和HashMap之间的区别,那么为何这道面试题如 ...
- 你不得不知道的HashMap面试连环炮
为什么用HashMap? 简述一下Map类继承关系? 解决哈希冲突的方法? 为什么HashMap线程不安全? resize机制? HashMap的工作原理是什么? 有什么方法可以减少碰撞? HashM ...
- 记一次Java面试问题点总结
引言 昨日接了一个阿里外包的电话面试,问了一些技术问题感觉到自己是真的菜,接触Java开发已经也有一段时间,技术方面说来惭愧,一直以来只是局限于框架工具的用法,也没有进行了解其实现的原理,更重要的是一 ...
- HashMap面试知识点总结
主要参考 JavaGuide 和 敖丙 的文章, 其中也有参考其他的文章, 但忘记保存链接了, 文中图片也是引用别的大佬的, 请见谅. 新手上路, 若有问题, 欢迎指正. 背景 HashMap 的相关 ...
随机推荐
- Python爬虫爬中文却显示Unicode,怎样显示中文--问题解答
首先爬取古诗网站时,显示 原因是因为输出为列表[] 如果写一个循环,输出其中每个元素就为中文了...
- Android开发环境的发展演变调研
Android开发环境的发展演变调研 前几年比较多的方法是用JDK+eclipse+ADT,该方法除了要配置JDK的路径之外, 还要在eclipse里面打开SDK Manage进行相应的操作.不过近两 ...
- 第二个spring冲刺第6天
今天的进展不多,对代码重新进行了整合,看起了比较简洁
- 使用HTTP协议向服务器传参的方式及django中获取参数的方式
使用HTTP协议向服务器传参的四种方式 URL路径携带参数,形如/weather/beijing/2018; 查询字符串(query string),形如key1=value1&key2=va ...
- Adobe X沙箱
一.Adobe X沙箱简介 Adobe Reader X自从引入沙箱以来,对其攻击的难度就提高了很多.Reader X的沙箱是基于Google的Chrome沙箱,Chrome是开源的,Reader X ...
- 微信小程序简易table组件实现
前提:微信小程序自1.6.3基础库版本库开始支持简洁组件,之前的版本因不支持,故在引用组件处默认为空节点.关于微信小程序已有模板为何还需构建组件?一是因为组件可以更方便的自定义并绑定行为,二是在其他页 ...
- 使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突
使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种冲突 如果你还在为处理滑动冲突而发愁,那么你需要静 ...
- php 中的 “!=”和“!==”
!==是指绝对不等于,比如,$a = 2, $b=”2″ 那么,$a!==$b成立,可是$a!=$b不成立:
- Java 工厂方法模式
在工厂对象上调用创建方法,生成接口的某个实现的对象 通过这种方式,接口与实现分离 方法接口 /** * 方法接口 */ public interface Service { void method1( ...
- python 实现二叉树的深度 & 广度优先遍历
什么是树 在计算器科学中,树(英语:tree)是一种抽象数据类型(ADT)或是实现这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>0)个有限节点组成一个具有层次关系 ...