标签:zed tab 不可 平衡 质数 知识 不用 付出 value
现在是晚上11点了,学校屠猪馆的自习室因为太晚要关闭了,勤奋且疲惫的小鲁班也从屠猪馆出来了,正准备回宿舍洗洗睡,由于自习室位置比较偏僻所以是接收不到手机网络信号的,因此小鲁班从兜里掏出手机的时候,信息可真是炸了呀,小鲁班心想,微信群平时都没什么人聊天,今晚肯定是发生了什么大事,仔细一看,才发现原来是小鲁班的室友达摩(光头)拿到了阿里巴巴JAVA开发实习生的offer,此时小鲁班真替他室友感到高兴的同时,心里也难免会产生一丝丝的失落感,那是因为自己投了很多份简历,别说拿不拿得到offer,就连给面试邀的公司也都寥寥无几,小鲁班这会可真是受到了一万点真实暴击,不过小鲁班还是很乐观的,很快调整了心态,带上耳机,慢慢的走回了宿舍,正打算准备向他那神室友达摩取取经。
片刻后~
小鲁班:666,听说你拿到了阿里的offer,能透露一下面试内容和技巧吗
达摩:嘿嘿嘿,没问题鸭,叫声爸爸我就告诉你
小鲁班:baba(表面笑嘻嘻,心里MMP)
达摩:其实我也不是很记得了(请继续装),但我还是记得那么一些,如果你是面的JAVA,首先当然是
小鲁班:问这么多内容,那岂不是一个人都面试很久吗?
达摩:不是的,面试官一般都会用连环炮的方式提问的。
小鲁班:你说的连环炮是什么意思鸭?
达摩:那我举个例子
就比如问你HashMap是不是有序的?
你回答不是有序的。那面试官就会可能继续问你,有没有有序的Map实现类呢?
你如果这个时候说不知道的话,那这块问题就到此结束了。如果你说有TreeMap和LinkedHashMap。
那么面试官接下来就可能会问你,TreeMap和LinkedHashMap是如何保证它的顺序的?
如果你回答不上来,那么到此为止。如果你说TreeMap是通过实现SortMap接口,能够把它保存的键值对根据key排序,基于红黑树,从而保证TreeMap中所有键值对处于有序状 态。LinkedHashMap则是通过插入排序(就是你put的时候的顺序是什么,取出来的时候就是什么样子)和访问排序(改变排序把访问过的放到底部)让键值有序。
那么面试官还会继续问你,你觉得它们两个哪个的有序实现比较好?
如果你依然可以回答的话,那么面试官会继续问你,你觉得还有没有比它更好或者更高效的实现方式。。无穷无尽深入,直到你回答不出来或者面试官认为问题到底了
小鲁班捏了一把汗,我去。。。这是魔鬼吧,那我们来试试呗(因为小鲁班刚刚在自习室才看了这章的知识,想趁机装一波逼,毕竟刚刚叫了声爸爸~~)
于是达摩and小鲁班就开始了对决:
1.为什么用HashMap?
2.HashMap的工作原理是什么?
Node[] table=new Node[16] 散列桶初始化,table
class Node {
hash;//hash值
key;//键
value;//值
node next;//用于指向链表的下一层(产生冲突,用拉链法)
}
1.对Key求Hash值,然后再计算下标
2.如果没有碰撞,直接放入桶中(碰撞的意思是计算得到的Hash值相同,需要放到同一个bucket中)
3.如果碰撞了,以链表的方式链接到后面
4.如果链表长度超过阀值( TREEIFY THRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表
5.如果节点已经存在就替换旧值
6.如果桶满了(容量16*加载因子0.75),就需要 resize(扩容2倍后重排)
当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。
3.有什么方法可以减少碰撞?
4.HashMap中hash函数怎么是是实现的?
我们可以看到在hashmap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。如何计算这个位置就是hash算法。前面说过hashmap的数据结构是数组和链表的结合,所以我们当然希望这个hashmap里面的元素位置尽量的分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置的时候,马上就可以知道对应位置的元素就是我们要的,而不用再去遍历链表。 所以我们首先想到的就是把hashcode对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,能不能找一种更快速,消耗更小的方式,我们来看看JDK1.8的源码是怎么做的(被楼主修饰了一下)
static final int hash(Object key) { if (key == null){ return 0; } int h; h=key.hashCode();返回散列值也就是hashcode // ^ :按位异或 // >>>:无符号右移,忽略符号位,空位都以0补齐 //其中n是数组的长度,即Map的数组部分初始化长度 return (n-1)&(h ^ (h >>> 16)); }
简单来说就是
1.高16bt不变,低16bit和高16bit做了一个异或(得到的HASHCODE转化为32位的二进制,前16位和后16位低16bit和高16bit做了一个异或)
2.(n·1)&hash=->得到下标
5.为什么要用红黑树?为什么不一直使用红黑树?
为了解决二叉查找树的缺陷,二叉查找树在特殊情况下会变成一个线性结构,查找会非常慢。我们知道红黑树属于平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树。
6.说说你对红黑树的见解?
7.解决hash 碰撞还有那些办法?
开放定址法。
当冲突发生时,使用某种探查技术在散列表中形成一个探查(测)序列。沿此序列逐个单元地查找,直到找到给定的地址。
按照形成探查序列的方法不同,可将开放定址法区分为线性探查法、二次探查法、双重散列法等。
下面给一个线性探查法的例子
问题:已知一组关键字为(26,36,41,38,44,15,68,12,06,51),用除余法构造散列函数,用线性探查法解决冲突构造这组关键字的散列表。
解答:为了减少冲突,通常令装填因子α由除余法因子是13的散列函数计算出的上述关键字序列的散列地址为(0,10,2,12,5,2,3,12,6,12)。
前5个关键字插入时,其相应的地址均为开放地址,故将它们直接插入T[0],T[10),T[2],T[12]和T[5]中。
当插入第6个关键字15时,其散列地址2(即h(15)=15%13=2)已被关键字41(15和41互为同义词)占用。故探查h1=(2+1)%13=3,此地址开放,所以将15放入T[3]中。
当插入第7个关键字68时,其散列地址3已被非同义词15先占用,故将其插入到T[4]中。
当插入第8个关键字12时,散列地址12已被同义词38占用,故探查hl=(12+1)%13=0,而T[0]亦被26占用,再探查h2=(12+2)%13=1,此地址开放,可将12插入其中。
类似地,第9个关键字06直接插入T[6]中;而最后一个关键字51插人时,因探查的地址12,0,1,…,6均非空,故51插入T[7]中。
8.如果HashMap的大小超过了负载因子(load factor)定义的容量,怎么办?
默认的负载因子大小为0.75,也就是说,当一个map填满了75%的bucket时候,和其它集合类(如ArrayList等)一样,将会创建原来HashMap大小的两倍的bucket数组,来重新调整map的大小,并将原来的对象放入新的bucket数组中。这个过程叫作rehashing,因为它调用hash方法找到新的bucket位置。这个值只可能在两个地方,一个是原下标的位置,另一种是在下标为<原下标+原容量>的位置
9.重新调整HashMap大小存在什么问题吗?
HashMap的容量是有限的。当经过多次元素插入,使得HashMap达到一定饱和度时,Key映射位置发生冲突的几率会逐渐提高。这时候,HashMap需要扩展它的长度,也就是 进行Resize。1.扩容:创建一个新的Entry空数组,长度是原数组的2倍。2.ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。
(这个过程比较烧脑,暂不作流程图演示,有兴趣去看看我的另一篇博文"HashMap扩容全过程")
达摩:哎呦,小老弟不错嘛~~意料之外呀
小鲁班:嘿嘿,优秀吧,中场休息一波,我先喝口水
达摩:不仅仅是这些哦,面试官还会问你相关的集合类对比,比如:
10.HashTable
11.HashMap ,HashTable 区别
12.ConcurrentHashMap 原理
- sizeCtl :默认为0,用来控制 table 的初始化和扩容操作。
- -1 代表table正在初始化
- N 表示有 -N-1 个线程正在进行扩容操作
- 如果table未初始化,表示table需要初始化的大小。
- 如果table初始化完成,表示table的容量,默认是table大小的0.75倍,居然用这个公式算0.75(n - (n >>> 2))。
13.我们可以使用CocurrentHashMap来代替Hashtable吗?
此时躺着床上的张飞哄了一声:睡觉了睡觉了~
见此不太妙:小鲁班立马回到床上(泉水),把被子盖过头,心里有一丝丝愉悦感,不对。好像还没洗澡。。。
转载请注明出处,谢谢
标签:zed tab 不可 平衡 质数 知识 不用 付出 value
原文地址:https://www.cnblogs.com/zhuoqingsen/p/HashMap.html