有假发,我自信我是带着假发的程序员。这一期我们来说说 jdk 一点八中 pass map 是如何确定一个元素应该放在数组的什么位置的?上一期中有的朋友说我讲的扩容讲错了,我会在下一期 蒋扩荣的视频中进行解释,欢迎关注。那么当我们执行下面的代码时,还是 map 到底做了什么?首先还是 map 在虐的时候是不会出事化数组的, 在第一次执行 pos 房法的时候,会先初始化数组,数组的长度默认是十六,当然即使你指定的默认容量他是 map, 也会将初始容量修改为大于或者等于你指定的值得一个二的。整次秘书我们继续回到 pos 方法中添加元素的操作。 pass map 会对加入的元素的批进行一个还是运算,如果批是 no, 则计算的还是值为零,如果批不是 no, 会进行如下的计算,源马如下。 具体的操作就是首先获取 p 的 hashcoat, 通过将 p 的 hashcoat 的右移十六位将高位扩展到低位,然后再使用原来的 hashcoat 和移动后的直进行抑或运算,目的是为了降低 hash 碰撞。再将得到的结果和数组的长度减一的数字进行与运算,源码如下, 这里会得到一个零到 lex 减一的数字,这就是这个元素要放的位置。我们来看一些具体的例子,比如使用默认的方式创建 s map, 数组长度为十六,放入的 t 为 hello, hello 的 so 的是九九幺六二三二二转成二进之为 经过右移十六位得到结果如下。再使用 hello 原生的 hascode 和右移十六位之后的直进行一或运算得到结果,九九幺六三四五幺二进制表示为在使用数组的长度减一十五和上面得到的结果 进行语运算得到结果转成实际制就是十一,所以这个元素在数组中的缩影就是十一。通过观察上面的计算,我们不难发现,任何数字和十五进行与运算得到的结果必然在零到十五之间。如果数组的长度是三十二,那么就是 has 得到的结果和三十一进行与运算。 三十一的二禁制表示形势如下,同样的道理,任何数字和三十一进行与运算得到的结果也是零到三十一之间。 在这个过程中如果产生的了 hish 碰撞,就会使用链表或者红黑树或者扩容。这部分内容我们下期再说,关注假发,每天学习奇怪的知识。
粉丝1.4万获赞4.0万

这节我们来学习哈西曼虎,今天内容有七点。首先我们来介绍一下什么是哈西曼,哈西散念或哈西的意思, 迈普映射的意思。哈西迈普,哈西映射,顾名思义,他是以 k v 六形式测出数据的,而且这些数据保存在数组中,默认的初始容量为十六。 数组的特点是有序,但哈奇卖部里面的元素并不是按顺序存放的,而是先根据 k 计算出元素的哈奇值。在鱼上数组容量减一, 这个操作等同与数的容量,取于得到的与数就是元素的位置,如此以来,势必会有多个元素被分配到同一个位置上。那该怎么办呢?他先慢步用 列表将这些元素单向的连接起来,这样就解决了多个元素位置冲突的问题。这样存了以后该怎么取呢?取出的顺序先从数组下边名开始,再从列表头节点开始,意思是柠檬、苹果、香蕉、葡萄 一次。究竟是不是这个顺序?我们来写一个程序验证一下,从执行结果来看,和我们刚刚说的顺序一致。说到这里,我们可以总结出汉斯曼普的第一个特点,五序元素从容的顺序和取出的顺序不一致, 这也是他唯一的缺点。接下来再来看哈西漫步的第二个特点,我们在计算元素哈气值的地方发现了退还可以围绕,并且还给他分配了哈气值, 是您。由此我们可以总结出哈西漫步的第二个特点,可以可以为让,并且哈气值为零。接下来再来看哈西漫步的第三个特点, 通过前面的知识,我们知道 k 相同,哈气值就一定相同,位置也相同,出现这种情况,新值会覆盖旧值。由此,我们可以总结出哈欠漫步的第三个特点, k 不可以重复,重复的 k 新值会覆盖旧值。接下来再来看哈西重土是怎么回事,他是两个不相同的 k, 产生了相同的哈西值。 我们把这种情况称之为哈西重土,也叫哈西碰撞。发生碰撞的本质还是取值范围的问题。例如一个二定周围,他的取值范围是零到一,落在它里面取哈西 的话,要么是零,要么是一,此时发生碰撞的概率是二分之一。也就是说,如果有三个 k 十,就一定会发生碰撞。如果我们将哈吸值的长度扩大到十六个二斤周围,那么他的取出范围就会越大,发生碰撞的概率就会越小。 在哈气慢破中,哈气值是硬特类型,四个字节长度是三十二个二斤周围碰撞的概率是四十二分之一。更长的哈气值意味着发生碰撞的概率更低,但也需要更大的存储空间和更多的计算, 我们需要在性能和成本之间做好权衡。接下来再来看什么是竖画?什么是念画。竖画是当列表长度大于八,且数字容量大于等于六十四时,将列表转换 化为红灰数。红灰数是一种自平衡的二招数,这样做的目的是为了提高查询速度,因为列表一旦长了以后,查询就会变得很慢。另外,红灰数也会变回列表。当红灰数中的节点小于等于六时,红灰数将转化为列表, 这个过程称之为炼化。此时的节点数很少,列表与红灰数的差距速度不相上下,而且在新增元素的时候,列表不用计算结点的位置直接插在尾部,但红灰数还有计算结点的位置, 他们两个相互转换可以形成很好的互补。大家需要注意的是,哈西万户在杰西 k 一点八中才引入的红灰数,以前采用的是数组加列表这种形式。 接下来再来看看新买部如何扩容。当元素个数超过零戒指时,看新买部就需要扩容。 银戒指等于容量乘以负载因子,扩容后的容量是之前的两倍。频繁扩容很影响哈西万普的性能,所以设置合适的初始容量与负载因子至关重要。接下来再来看哈西万夫的常用方法有哪些。哈西万夫实现了漫步接口, 拥有迈克里面的所有方法,但是在这些方法里面,他只有八个方法是常用的, 其中铺头和对的方法用的最频繁。最后总结下本节内容,本节介绍了哈西映社哈西漫步他的特点及优缺点,这里就不带坠数了,在实际开发中,他是用的最 频繁的容器之一,多用于缓存数据。这截的方法分类图和详细说明我放在了 gitth 上,大家如果有需要的话可以前去查看。


今天威哥给大家解析一道源自阿里一面且非常经典的面试题哈奇 map 的普特原理。首先来说几点前置知识,哈奇 map 的数据结构, j d k 一点七数组加链表 j d k 一点八数组加链表加红黑数 数组链表的特点,数组寻指容易,增山困难链表寻指困难,增山容易也得可以点吧。为什么要使用红黑数?其实归根到底就是为了解决链表过长的问题。 接下来我们就开始解析这道面试题,如果我是面试官,我则更希望面试者能够从 j t k 一点七和 j t k 一点八两个版本分别去阐述。 好,那我们就先聊一下 gdk 一点七中哈奇迈普的扑的原理。首先判断哈奇迈普是否为空,如果是,则调用 inflatable 方法完成。对 对该哈奇迈普数组进行初始化。接着判断 k 是否为空,为空则便利以 table 下标令为首的列表寻找是否存在 k 等于空。对应的剑指队,如果存在则完成覆盖,不存在则调用 i 的 h 方法完成 k 和 y 六的插入。 k 不等于空,则根据 k 计算数组的锁印值。循环列表判断 k 是否存在,存在则完成覆盖,不存在则调用 it n 处方法。最后让我们一起来看一下 it n 处方法。 先判断是否需要扩容,如果要扩容,则进行扩容,如果不用扩容,则生成 intry 对象,使用头插法添加到当前位置的列表中。接下来让我们结合流程图再来看一遍流程。首先判断哈欠卖部是否为空,如果是,则调用 inflat table 方法完成数组的初始化。 接着判断 k 是否为空,如果是,则便利 table 下边零为首的列表,寻找是否存在 k 等于空。对应的箭指队如果存在则完成覆盖,不存在则调用 idang 方法。 k 不等于空时,则根据 k 计算数组的所引值 循环列表判断 k 是否存在,存在则完成覆盖,不存在则调用 identry 方法。 identry 方法首先判断是否需要扩容,如果需要扩容则完成扩容。 最后生成 n 锤对象,使用头插法插入到当前列表中。好,最后的原码分析部分建议小伙伴们自己看一下笔记,如果有任何疑问,可以随时和威哥进行交流 哦。接下来让我们看一下 j d k 一点八中哈西迈 破的原理。好,首先判断哈奇迈普是否为空,如果是,则都要用 reset 方法进行扩容,在这里其实就是进行初始化。接着通过运算得到数组下标,如果数组下标元素为空,则直接放入。如果数组下标元素不为空, 则首先判断数组上该位置的 k 是否相同,相同则执行覆盖操作,不相同则判断该节点上 note 的类型,判断是红黑数还是链表,如果是红黑数,则执行红黑数的插入逻辑, 在这个过程中会判断红黑数中是否存在当前 k, 如果存在则完成更新。如果是链表操作,因为 jdk 一点八中链表采用的是尾插法,所以需要便利链表,在便利链表的过程中会判断是否存在当前 k, 如果存在,则完成更新。便利完链表之后,将 豆的节点插入到列表中,最后会判断列表的节点个数如果大于等于八,同时哈奇迈步的数组长度大于六十四,那么则会将该列表转为红黑数。最后 则是进行扩容操作。好,接下来让我们结合流程图再来看一遍流程。好,首先判断哈奇迈步是否为空,如果是,则调用 reset 方法进行扩容。 接着根据 k 计算数组的锁引值,判断该数组锁引值上的元素是否为空,如果是,则直接完成插入操作。如果不是,则判断数组上该接点 k 是否相等,是则直接覆盖。如果不是,则判断该接点是红黑数接点还是 链表结点,如果是红灰数结点,则完成红灰数的插入逻辑。如果是链表,则需要便利链表判断该链表上 是否存在该 k, 如果是,则直接覆盖,如果不是,则采用尾插法直接插入到链表的尾部。最后判断链表的长度是否大于八,同时哈气迈普的数组长度大于六十四,如果满足,则转化为红黑数。最后 判断是否需要扩容。最后的原码部分还是建议小伙伴们自己看一下笔记,如果有任何疑问,可以随时和威哥进行交流。好,最后让我们看一下知识拓展部分,请对比下 gdk 一点七和 gdk 一点八中哈西迈普的破的方法。 首先出手化方式上, jdk 一点七调用的是引弗雷的退步方法, jdk 一点八则调用的是 reset 方法。哈西值的计算方式, jdk 一点七采用的是九次扰动,这个在刚才原码部分有详细说明, jdk 一点八采用的是两次扰动。底层数据结构部分, jdk 一点七采用的是数组加量秒, jdk 一点八则采用的是数组加量秒加红黑数插入数据的方式。 jdk 一点七采用的是图插法, jdk 一点八采用的是尾插法。为什么默认的初始容量必须是二的 n 次密,主要是为了服务于可以到 intex 的哈西算法。我们知道哈西算法有两个选择,一个是未运算,一个是曲余,当然我们选择效率更高的未运算。 很多人认为只有在容量是二的 n 次密的时候, index 一才等于 index 二,为了使用效率更高的不运算是这道题的解释,但是我不是这么认为的,或者说这不是主要原因。原因一, index 一等不等于 index 二本身就没有意义,因为 引代克斯二计算出来的一样是数组长度范围内的锁引下标,不一定非要引代克斯一等于引代克斯二,原因二也是我认为的这道题的答案。只有容量是二的密次方的时候,长度减一的值得,二进制的低位才全为一。 在这种情况下, index 的结果取决于哈西扣的二进制的地位,只要输入的哈西扣的本身分布均匀,哈西算法的结果就是均匀的, 不是二的 n b 次方则受低位影响比较大,导致哈西分布不均匀。为什么负载因子为零点七五? 首先,根据牛顿二式计算出来的时间和空间比,最好的权衡的值是零点六九三。第二,因为容量必须是二的密次方,所以为了保证容量成亿,负载 因子是一个整数,取值零点七五是一个比较合理的值。为什么杰迪 k 一点八中链表转红黑处的必要条件之一是长度大于八,纯 note 占用的内存是 note 的两倍,只有在长度大于八时才会使用红黑树。当哈衣库的遵循 博松分布时,长度为八的概率为一分之六,官方认为这个概率足够的低,所以才把这个值定为八。好,让我们看最后一道拓展题,为什么等于六十?又把红黑数转化为列表? 通过薄松分布可以看到,当红黑树节点数小于六时,他带来的优势已经没有那么大了,不足以抵消由于红黑树维护节点带来的额外开销,此时转化为列表能节省空间和时间。好小伙伴们,关注威哥,更多精品内容持续与你分享!

找到下载好的 java 和冰蝎,解压冰蝎压缩包 安全中心添加排除项, 使用 java 安装程序,安装 java, 第一次安装 jdk 文件, 第二次安装 java 文件 win 加二,输入 cmd, 打开 show, 查看 java 版本 配置系统环境变量, 新建系统变量, 变量名为 java jdk 变量值为 java 中的 jdk 文件夹, 编辑系统变量 path, 新建变量,变量为 jdk 文件夹中的 bim, 进入冰蝎文件夹,在路径中使用命令启动冰蝎 没有找到 j d k 环境,查看使用了哪个路径的程序来启动,记住这个路径,然后在环境变量中进行删除。 删除第一条变量, 新使用 java 命令打, 这次是使用 jdk 中的程序来启动。

深入理解哈西卖铺与哈西算法,首先我们来讲一下哈西卖铺的数据结构,在 java 七以及 java 七以及以前,哈西卖铺的底层是数组加列表,像这样的 默认情况下面的元素放在数组上,如果说他们中间发生了哈西冲突,也就是说在一个数组上面,我要插多个元素,他就会形成这样的一个单列表,这就是哈西麦普 gdk 一点七以及以前他的数字结构。那么到了扎瓦八中间之后的话呢,除了数组和列表之外,他还加入了鸿飞数,也就是说 如果链表的长度过长,他在一定条件下面可能会转换成一棵红黑树。那什么情况下面链表会转换成红黑树呢?他要满足的条件就是第一个链表的长度必须要大于八,就是这个长度必须大于八。然后与此同时还要注意一个点,就是他还需要满足第二 条件,就是数组的长度必须要大于等于六十四,也就是说默认情况下面,你又出来的,又出来的这个哈西迈普,他的数组是六十四,是一十六个长度,对不对?这个地方你要经过两次扩容变成六十四之后,当列表的长度大于等于八了之后, 那么这个链表才会转成红黑树,才会转成这个样子,否则的话呢,他只会触发哈西麦普当中数组的扩容,也就是说他仅仅只会把这个数组呢进行乘以两倍, ok, 所以呢,这就是链表 什么情况下面会转成同回数?要注意了,是有两个条件的,不单纯是列表大于八,还要满足数组的长度呢,他一定是要大于等于六十四, ok, 好,我们再来讲一下哈西卖谱当中的哈西算法,其实要讲清楚哈西算法的话,我们必须要去讲他的 pow 的方法和 get 方法,但是不 管是哈西卖部当中的扑特还是他的 get, 他的流程是类似的,比如说第一步先根据 t 值来计算出哈西值,然后第二步根据这个哈西值来算出这个数组的下标, ok, 然后的话呢再进行对应的,比如说插入,插在数字上面,或者插在列表上面,或者插在横汇数上面, 或者是进行对应的查询,所以呢,这就是哈西卖部当中的一个库的 get 方法,他的一个流程。那么我们来看一下,在这里面呢,他就会涉及到两个算法,第一个的话呢,就根据 k 来计算哈西,第二个话呢,根据哈西来算出数字的下标。 首先在原码当中,我们来找一下根据 k 计算出哈西的这种方法,那么这个 k 呢,是个入餐对不对?然后的话呢,你会发现它里面进行了一个三目运算,如果这个 k 等于空,直接返回一个零, ok, 如果说他不为空,那么首先拿到这一个 他的哈西克的值,拿到之后再做一个处理,把这个值呢付给 h, 然后呢再用 h 这个本身对不对?和这个 h 向右无符号位一十六位做一个优惠运算,最终得到一个改进型的哈西阔的, ok, 然后这就是根据 t 怎么去算哈西?这是第一个算法,然后第二个算法的话,你会发现啊,他在根据这个哈西值再来去算出对应数字的下标,也就是说我得到这一个哈西值,然后的话呢,再去 跟这个 n 减一,进行一个雨计算,也就是说我们得到的哈西值再跟这个 n 减一,进行一个雨计算, ok, 这样呢得到一个对应的数组下标,那么这个 n 是什么呢?这个 n 是为数组的一个长度,那么为什么他可以算呢?我要讲一下,因为 这么去运算,他的效果其实跟哈西值去个 n 曲模他是一样的,但是他满足的条件就是必须这个 n 是二的次方,当然在哈西卖部当中 他是二的四方,所以呢这样的运算他的效果是一样的。与此同时的话,因为他是个雨计算,看到没有,在计算机里面雨计算他的运算速度一定比我们的这种曲模运算他的效率要高,所以这种算法效率更高。好,这是第一个点, 第二个点就是在 gdk 一点八当中,为什么要采用这么复杂的哈吸值的计算方法呢?明明你通过一个 k 直接调用哈吸扣的方法可以拿到一个哈吸值,为什么还要采用这样的运算呢? 其实原因很简单,就是为什么哈西卖普要把哈西扣的做一个改进,就是让他算出的数组下标更加分散,就是让我们算出了这个哈西值,然后再经过数 下边的运算,他得出的结果会更加的分散。原因是什么呢?我们来看一下。如果说我们就不进行这种运算,我们拿到一个哈西扣的,然后拿到这个哈西扣的之后,我们再跟 n 减一,进行一个语计算, n 是什么? n 是 数字的长度对不对?比如说数字的长度是一十六,那么这个情况下面呢,他 n 减一,他就是一十五,然后用二进去表示就是四个幺, ok, 然后高位全是零,你们进行一个语句算的时候,大家发现没有, 这个哈西值得出的数组下标,他只跟低位有关,就是你这个哈西值的高位,其实他不会去参与到我们数组下标的运算,也就是说如果你不对这个哈西扣的进行改进,那么这种 n 减一与上哈西的这种计算数组下标的 方式,他始终会导致很大的哈西通途,因为你有可能计算出来了哈西值,对不对?明明他的低位都是相同的,只是高位不同,于是高位很多的东西不同,那么低位只要第四位,第五位相同,那么他们算出的数组下标一定相同,所以这样的情况呢,就不利于哈西分散, 所以的话呢,在哈西卖普里面就用这样的方式进行了一个改进。怎么改进的?首先把这个哈西扣的复制给 h, 好,那么我们得到一个 h, 那么大家知道啊,这一个哈西扣的他是一个三十二位的,那当然有低一十六位和高一十六位,对不对?这个时候呢,我们再把这个 h 向右无符号位于一十六位,得到一个另外的结果,那么你可以发现这个 h 向右边无符号位于一十六位,就相当于是往右边推进,那相当于是把这个高一十六位,把它放到这 第一十六位,对不对? ok, 然后的话呢,这个高位就补零,然后他们中间再来完成一个预后运算,也就是说通过这种计算比较均匀的预后运算,最终会得到一部分影响数组下标的这样的一个哈西值, 所以你发现这样的一个算法的改进的话呢,他就会会让这种高一十六位也会去参与到影响数组下标运算的这些低位的这个哈西值里面来。 如果说你不采用这样的运算,那么你的数组下标了可能会更加的什么有哈气冲突。如果我采用了这样的运算,那么高一十六位他也可以去参与我们的这个数组下标的计算的一个影响,所以他会让我们的下标计算 更加的分散,所以这就是哈西卖部当中他对哈西 coat 做的一个算法改进。

哈西麦部死循环呢,是一个比较常见也是比较经典的面试题,在大爽的面试中呢,经常会被问到哈西麦部的死循环问题呢,只是在 gdk 一点七中会出现,主要是哈西麦部自身的过度机制,再加上并发操作,总而会导致死循环的出现。在 gdk 一点八以后呢,官方彻底的解决了这个问题。 在分析原因之前啊,我先带大家来了解一下 gdk 一点七中他先迈普插入数据的原理来看动画的演示。 由于接地根一点七中哈西麦普的底层的存储结构采用的是数组加列表的方式,而哈西麦普呢,在插入数据的时候采用的是头插法, 也就是说新人插入的数据会从列表的头结点进行插入。因此呢,哈西卖部正常情况下的扩容就是这样一个过程。我们来看旧的哈新卖部的节点会依次转移到新的哈新卖部中,旧 哈新漫步转移列表中的元素的顺序是 abc, 而新哈新漫步使用的是头插法,所以扩容完成后,最终在新哈新漫步中列表元素的顺序是 cba。 接下来我通过动画演示的方式带大家彻底理解哈西曼普死循环的原因,我们按以下三个步骤来还原并发传奇下哈西曼普扩容导致的死循环问题。第一步,现成启动。假设有现成第一和现成第二,都准备对哈西曼普进行扩容, 此时 t 一和 t 二都指向的是列表的头结点 a, 而 t 一和 t 二的下一个节点分别是 t 一点 nex 和 t 二点 nex, 他们都指向 b 结点。第二步,开始扩容,这个时候假设现成 t 二的时间片用完了,进入了修眉状态,而现成 t 一呢 呢,开始执行扩容动作,一直到县城第一扩容完成后,县城第二才被唤醒。县城第一完成扩容之后的场景就变成了东方显示的这样,因为他先把我扩容采用的是头纱法。县城第一执行之后呢,列表中的节点顺序发生了变化, 但是县城 t 二对于发生的一切是不可知的,所以他只是在节点引用,依然没有发生改变。如图所示, t 二指向的是 a 节点, t 二点那个是指向的是 b 节点。当县城 t 一执行完成之后呢,县城 t 二恢复执行死刑完,这时候就发生了,因为 t 一执行完成扩容之后啊, b 节点的下一个节点就是 a, 而 t 二线层直线的首结点是 a, 第二个节点呢是 b, 这个时候顺序刚好与 t 一扩容之前的节点的顺序是相反的, t 一直线完以后的顺序是 b 到 a, 而 t 二直线的顺序是 a 到 b, 这样 a 节点和 b 节点就形成了死循环。避免哈西麦普方在死循环的常用解决方案有三个,第一个使用现场安全的看看里的哈西麦普来替代哈西麦普这个个人呢,推荐使用 第二个使用现场安全的容器哈西太伯的替代,但他的性能比较低,不建议使用。第三个使用是一个 nice 的或者 log 加锁之后再进行操作,相对数多线程排队执行,但是呢,这也会影响性能,所以呢,也不建议使用 哈仙麦普死循环指方式在 gdk 一点七版本中,主要原因是 gdk 一点七中的哈仙麦普在头插法加上列表,再加上多线层并发,再加上扩容,几个情形,哪家在一起就会形成一个死循环。 而多线的环境呢?建议采用的是康康的海鲜卖部来替代。在 gda 一点八中呢,海鲜卖部改成了尾插法, 解决了列表死循环的问题。以上的就是关于哈西曼的死循环原因的分析,听懂的小伙伴关注点个赞,下次不迷路,我是被编程耽误的文艺汤。 如果还有其他疑问或者想要高见五马毒的小伙伴,请在评论区留言,如果我的分享对你有帮助,请你动动手指,一键三连分享给更多的人!关注我,面试不再难!

原码分析 j、 d、 k 一点八的 concurrent hash map 初始化数组流程揭秘 hello, 大家好,我是架构师奶爸。我们在创建 concurrent hash map 时,通常有以下两种做法一个是午餐构造, 一个是初始化容量的有参构造方法。这两个构造方法中都没有对内部的数组做初始化,无参构造中没有维护任何变量的操作。如果调用该方法,数组长度默认是十六。如果传递进来一个初始容量, concurrent hash map 会基于这个值计算一个比这个值大的二的密次方数作为初始容量。所以我们直接点进 put 方法看。我们可以很明显地看到 concurrent hash map 是不允许 key 或者 value 为空的。 然后基于当前 t 计算了一个 hash 值,然后定义了一个 bit count, 然后往下走,进入了一个 for 循环。在这个 for 循环中,首先拿到当前操作的数组对象,然后判断是否为 no, 如果为 no, 则调用 unit table 方法进行初始化。那我们就来看看 concurrent hash map 的初始化机制。一、 他使用了一个自炫的方式,保证在这个过程中数组没有被其他县城初始化。二、第一个判断 sc 默认为零是否小于零。这个值就是一个记录参数。 如果小于零,则调用 threat 类的 yield 方法。该方法的意思是让当前这个县城暂时放弃当前 cpu 的资源,让他重新去竞争资源。三、默认情况下, 走下面的分支,通过 cas 操作让 sc 减一,并且存入内存中。因此,如果有多个县城进行 cas 的话,只有一个县城能够减成功, 其他县城重新进入循环的时候再去进行判断。 sc 就会拿到内存中已经减一的值,那么就会放弃当前 cpu 的资源, 保证了县城安全。四、检成功之后,再去进行一次数组为 no 的判断。这里其实就是一个 d、 c l、 d wu check lock 双重检查所的处理。五、 然后去获取数组的容量。如果我们使用了有参构造器,指定 s c 的话,就使用 s、 c。 如果我们没有指定初始化容量,那么就使用默认的初始化容量,默认为十六。六、 创建 note 数组,并赋予容量。七、再去记录一下 s、 c 与 size c、 t、 l。 这个时候 s、 c 就等于初始容量 n, 减去初始容量 n 左移两位四分之一,也就是零点七五乘以 n 八。相当于在初始化数组的时候,我们就记录了后面扩容的预值 size c、 t、 l。 至此,初始化数组的流程就结束。 如果数组已经初始化过了,进入第二次循环,就进入真正的破流程。详细的原码分析请看下一个视频。想学习更多 java 编程知识,请关注我架构师奶爸,共同筑基 java 架构师。

康康日的哈西麦普相当于是哈西麦普的多线层版本,他的功能呢,本质上和哈西麦普没什么区别,因为哈西麦普呢,在并发超出的时候啊,会出现各种问题,比如说死循环问题,数据覆盖等问题, 而这些问题呢,只要使用康康康康康康康康康福就可以完美的解决。那么问题来了,康康康康康康康康康康康康康康康康康康康康康康康康康康康。他是如何去保证现场安全的呢? 首先我们来看 gda 一点七中坑,看着他是曼普的底层的结构,他基本上延续了哈系曼普的基本设计,他采用的是数组加列表的形式, 和哈西曼不同的是,看开准哈西曼中的数组啊,被分为大数组和小数组,大数组是塞格门特,小数组是哈西安全。来看这张图,大数组塞格门特呢,可以理解这是一个数据库,而这个数据库呢,又有很多种表,这个表就是哈西安全。而每个 哈西安区中呢,又有很多家数据,这些数据呢,采用的是列表结构。了解了康康的哈西曼普的基本结构设计的话,再来看他的现在安全就比较简单了。接下来我们来对照 gdk 一点七中康康康的哈西曼普的圆码来进行理解,我们可以看到, 因为赛哥们的本身是基于润全的洛克重入锁的实现来加锁和释放锁的操作,这样的话就能够保证都县城同时访问看看的他去漫步的时候,同一时间只能有一个现身操作对应的节点,这样的话保证了看看的他去漫步的现场安全, 也就说康康的他是迈步的,现场安全是建立在赛克本的家属的基础上,所以呢,我们称他为分段所或者是分片所,如图所示。那接近个一点八又是如何实现的呢? 在这个一点七中啊,看看准的。航行方普虽然是现场安全的,但是呢,它的底层实现是采用数组加列表的。 是,所以啊,在数据比较多的情况下,因为要编辑整个列表,这样的话会降低他的访问性能。所以呢,接近一点八以后呢,就采用的数字加列表加红函数的方式进行的优化。那具体实现呢,如图数四,当我们的列表长度大于八的时候,并且呢,数组长度大于六十四的时候,列表呢就会升级为红函数的结构。 gda 八中呢,看看准的还是万普保留了三个门的定义,但是呢,这仅仅只是为了保证训练化的时候的兼容性,不再有任何结构上的用途了。那在 gda 八中 看哈西卖部的圆码又是如何实现的呢?它主要是使用的 cs 加 white 或者是申公赖子的方法来实现,保证现场安全。我们可以从圆码片段中看到,添加元素的时候啊,首先会判断容器是否为空,如果为空就会使用 white 加上 cs 来。说实话,如果容器不为空, 就会根据存储的元素计算该位置是否为空。如果根据存储元素的计算结果为空,就会利用 cis 的设计该节点,如果根据存储元素的计算结果不为空,就会使用 cci 的枷锁来进行实现。然后呢,去便利桶中的数据,并且替换或者新增结节到桶中。 最后呢,判断是否需要转为红函数,这样的话就保证了并发访问的时候的现场安全。如果把上面的执行用一句话来归纳的话,就相当于是坑看着呢,他去外婆通过对头节点加手来保证现场安全。这样设计的好处呢,是使得手的力度相比赛克门的来说更小了, 发生哈西冲突和家属的频率也更低了,而在并发商机上超出性能也提高了,而且呢,当数据量比较大的时候呢,查询性能也得到了进一步的提升。最后呢,我们来总结 下,第一点, ctrl 的哈西马普在 gda 七中啊,使用的是数组加列表结构,其中数组呢分为两大类,大数组呢是塞格门的,小数组是哈系安全,而加数呢是通过塞格门的添加 ran 群的 logo 重入数来保证现场安全的。 第二点,看卡人的航行,迈普在接近一点八中使用的是数组加列表加横和竖的方式来实现,他自动过 c s 或者是伸扣。 nice 的保证线上安全,并且呢也缩小了数的力度,查询新人也得到了进步的提升, 刚看准的行业卖不出来,有很多的设计思想是值得我们去学习和借鉴的,比如说力度的控制,分段数的设计, 这些都是可以应用到实际开发业务场景中,我们可以通过学习这些底层原理呢,去获得很多的这种设计思想,来帮助我们去更高效的去解决实际问题。以上呢就是关于看看的还是漫步的分享,听懂的小伙伴请关注点个赞, 下次不迷路,我是被奔驰耽误的文艺汤!如果还有其他疑问或者需要高清五码头的小伙伴,请在评论区留言,如果我的分享对你有帮助,请你动动手指,一键三连分享给更多的人!关注我,面试不再难!

有假发,我自信。这一期我们来说说 jdk 一点八中的 hasmap 的扩容机制。首先我们来看看 hasmap 的初始容量, hashmap 如果使用默认的方式创建,默认的初始容量是十六,如果我们指定了初始容量,比如指定为二十四,实际上 hasmap 会通过计算得到一个 大于等于二十四的二的整次秘书,三十二作为初始容量。为什么呢?因为二的正次秘书有统一的规律,可以通过为运算快速的计算出元素的,所以关于所以的计算在上一个视频中已经讲解过,这里就不再坠述。接下来我们来看看 hex map 扩容的情况。 hex map 在两种不同的情况下会扩容。第 第一就是元素个数到达了扩容的预值,这个扩容的预值是通过容量和负载因子计算的,默认的负载因子是零点七五,也就是说如果数组长度是十六,那么扩容的预值就是十二。如果数 数组的长度是三十二,那么扩容预值就是二十四,当然这个预值也是有最大值的。这部分后面再说。了解到这里,也就是说第一种扩容的情况就是当元素个数超过了当前的扩容预值,就会将数组扩容。那么接下来说第二种扩容的情况,在还是 map 中有一个最小数化容量 确认值是六十四。假如数组的某个位置上的链表个数到达了八个,但是数组的长度还没有到达六十四。 hash map 不会竖画这个链表,而是对数组进行扩容。这也是上上个视频中有朋友说我讲的有问题的部分。继续说 hash map 如何扩容?如果需要扩容, smap 会对原有的容量和扩容预值进行左移一位的运算,其实就是翻倍。根据新计算出来的容量值和预值创建新的数组,然后将原来数组中的所有元素重新计算位置,并且移动到新的数组上 对应的位置。当数组的长度大于或者等于六十四之后,如果某个列表的元素到达八个 hash map, 就会将这个列表转换为红黑数,当少于六个的时候又会转换为列表。继续说说 hash map 的容量上限。 house map 定义了一个最大的容量值 2 的 34 方,当数组的容量超过或者等于 2 的 34 方时,扩容的预值会直接设置为整形的最大值,也就是 2 的 31 次方减一。当然到达最大值的时候还是 map 也不会再扩容了。可能有人要问,不再扩容, 如果元素过多怎么办?其实一般情况都是还没有到最大值,内存就一出了。如果真的到达了最大值,并且数组所有位置都不为空,那么就是继续给对应位置上的列表或者红黑数继续添加新的节点,这就是 jdk 一点八中还是 map 的扩容。

接下来我们再来看一下阿里二面相关的一些面试题啊,当然有人说阿里一面就可能还有其他的,到时候大家如果说大家在面阿里的时候,哎,如果说还有其他的面试题啊,那么到时候也可以来发给 各位老师啊,到时候我也可以更新到这个视频上面,好吗?好,所以说接下来我们啊先来看几道关于阿里阿面的面试题啊。首先第一道啊,就是 jdk 一点七到 jdk 一点八之间,哈西迈普发生了哪些变化啊?在哈里很喜欢用,很喜欢问哈西迈普的啊,好, 好,那么,呃,当然这个主要说的还是底层啊,因为一点七到一点八你哈西迈克的用法其实没什么改变,对吧?所以我们来看一下他底层发生了哪些变化。首先啊,大家可能自己也能够想到,就是一点七里面用的是数组家电表,一点八里面用 用的是数组加电表加红黑素。当然啊,你形容一下为什么要加红黑素,因为加红黑素的目的其实就是提高哈西麦普插入和查询的整体效率,这是红黑素这个数据结构他本身的一个特点,插入和查询的这个效率都还算非常可以的。好, 那么,呃,在一点七中间还有一个不同,就是他的念表哎,他一点七里面念表的插入使用的是头插法啊,一点八中间念表的插入使用的是尾插法啊,那么为什么一点八里面要要改成尾插法?因为在一点八中间啊, 当我去插入一个 k 和弯路的时候,我需要去判断当前这个 k 所对应的那个列表上面元素的个数,那我们知道,我们要去知道一个列表上面有多少个元素,你肯定就得去便利这个列表去统计这个列表上面元素的个数,所以你便 另一个列表的话,你总归会被列到那个列表的尾,最后一个节点就是尾节点,对,那么正好你就可以把你新的啊 k 弯扭啊,这个东西要把它组成一个列表的节点,把它插到尾部,对啊,真的是 顺便的,顺带的一件事情啊。好,那么,呃,所以用违章法,那么同样的在一点七中间还有一个改动啊,一点八中间还有改动,就是关于这个哈七算法。一点七中间的哈七算法,它是比较复杂的啊,它里面存在各个 各种幼以运算,未以运算,包括亦或运算啊,真的,他之所以这个哈须算法是在这哈须算法越复杂,他就是所产生的那个哈须扣的的散列性就更好,那么这种 就会让我们的哈西迈普内部的元素分布的时候也就更加均匀,所以说这是他哈西算法复杂的一个原因。那么在一点八中间,他对这个哈西 算法啊,他进行的一个简化啊,因为简化负载均衡算法的目的啊,就是因为啊,这就是如果因为复杂的像我要说的复杂的哈西算法的目的是去提高闪电性,那么现在的简化了哈西算法,那么为什么可以简化?因为在一点八中间他正 清真的红黑素和红黑素哎,去把我们整个哈西迈普的差入和差距效率给提高了,所以我们适当的可以简化一下哈西算法,因为,呃, 像我们在 get 一个 k 或者说扑腾一个 k 的时候,其实你都要去经过哈奇算法,而哈奇算法如果说你很复杂,那么你其实就消耗了很多 cpu 的资源。现在,哎,我通过红黑素,我其实已经把哈西麦克的整体的插入场景效率已经提高了,所以我可以适当的去简化一下哈奇算法,去节省一下 cpu 的资源啊。所以说这是啊,这三点就是一点七到一点八之间,这个哈西迈普发生了一些变化。

有假发我自信。本期来说说 hash map, 我们这里说的是 j d k 一点八的 hash map。 hash map 的底层是通过数组和列表实现的。当我们插入一个 key value 时,首先会生成一个 note 对象, note 对象中有成员 key, value 和 next key 和 value 不用多说,这里的 next 指向下一个 note 对象。 当我们创建一个默认的 hash map 时,会在内存中创建一个长度为十六的数组,数组的类型就是 note。 那么我们应该把新添加的 note 放在数组的什么位置呢? hash map 会对 p 的 hash code 进行计算,得到一个零到十五之间的值。关于这个计算,我们后面的视频继续讲。 这里得到的零到十五的值就是这个 note 要存放的数组的锁引,但是不同的 p 有时会得到相同的锁引值,这时 hashcote 会判断新传入的 note 的 p 是否和已有的 note 的 p 相同。如果相 同,就会用新的 note 的 value 覆盖原有 note 的 value, 如果不相同,就会将新传入的 note 设置为原有 note 的下一个元素,形成一个链表。当一个链表上的元素个数到达八个的时候,为了防止元素过多导致的便利速度过慢, pass map 就会自动扩容,增加数组的长度,然后重新计算所有 note 的所引位置, 重新存储。但是如果数组扩容到长度为六十四之后,如果某个位置上的列表的元素超过过了八个, pashmap 会将这个列表调整为红黑数。 然后当这个红黑树上的元素少于六个的时候, hashmap 又会将这个位置上的红黑树调整成列表。当然, hashmap 的主水容量和树化容量预值都是可以调整的,这就是 j d k 一点八中的 hashmap 底层结构。关注假发,每天学习奇怪的知识。

说一下哈西麦普的一个 pro 方法,那么这个题目的话,我们要分情况讨论,就是要对比这个一点七和一点八的一个版本来讲, 那么我们先说一下大体的一个流程,那么根据呃 k 的话,第一的话先要根据 k 通过哈西算法和这个雨运算得出这个数组下标, 如果说这个数字下标位置元素为空的话,就将这个 k 和弯柳封装为 n 锤对象,那么在 g d k 一点七中式 n 锤对象 g d k 一点八中的话,就是 note 对象封穿成这个对象放入这个位置, 那么如果说这个数组下标的位置元素不为空,就要分情况讨论,如果说是 j d k 一点七,就要先判断是否需要去扩容,如果要扩容的话 就进行扩容,如果不要扩容就生成这个 h 对象,并且呢使用头插法去添加到当前位置的一个列表中, 那么如果说是 gdk 一点八,则会先判断这个位置上的一个漏的类型啊,是红黑素漏的还是这个链表漏的。 那如果说是红黑树 note 的,就需要将这个 k 和歪扭封装成一个红黑树节点,并且呢添加到这个红黑树中去,那么在这个过程中,我们会判断这个红黑树中是否就是存在这个当前的我们要加入的这个 k, 如果存在的话 就更新这个弯钮,那么如果这个位置上的这个 note 对象是链表节点的话,就要将这个 p 和弯钮封装为一个链表 note, 并且通过尾插法插入到链表的 一个最后位置去,因为是尾插法,所以呢需要便利练表,在便利练表的过程中就会去判断是否存在当前题,如果存在则更新 value。 当便利完这个链表的后啊,就将新的链表 note 插入到链表中,那么插入到链表后,就会看到当前链表的一个节点个数,如果说大于等于八啊,这里是大于等于八,那么就会将这个链表转成这个红黑数。 好,那将这个 k 和 v 六分装为 no 的插入的列表或者是红黑数之后呢,再判断是否需要进行扩容,那么如果需要进行扩容啊,就扩容,如果不需要就结束这个扩容方法。那么这里大家看一下 gdp 一点七的话,它是 先判断扩容再插入节点,而一点八的话,他是先插入节点,然后再去判断这个扩容啊,大家可以去对比一下他们的一个区别,那么这就是这样一个面试题。

就是这个全方位搞定哈西 map, 分析其源码,我们主要围绕的两个点,首先是哈西 map 会导致这个 dos 攻击啊,我们围绕这个攻击的话,他是怎么去产生?然后会给我们的这个程序造成什么样的影响? 我们围绕这个点,然后去展开一下,去分析一下。另外的话就是我们剖析一下哈西 map 的原码, 分析一下他的数据结构和算法。因为我们在学习哈奇麦克,哈奇麦克的时候,无非就是从两个点去去讨论他,或者是去了解他,一个就是数据结构,另外一个就是算法。 如果要再更详细一点的话,我们要了解一下哈奇 map 里面所涉及到的一些参数,我们对这些参数的话,它的作用会 或者是说我们为什么要用这些参数设定的值都是指定的这个值呢?比方说他的速度粗数化大小是十六,我们为什么要设置成十六呢?为什么不设置成十一十二? 另外的话,我们要对他的数据结构有所了解,对吧?他采用了哪些数据结构来保存我们的数据呢? 第第三个点的话,我们就是要了解他的哈西算法,他的算法有哪些?你比方说他的哈西算法,哈西冲突,他的数组坐标的定位如何定位的,对吧? 我们要了解他的算法,他的计算逻辑,他的核心的底层原理,他为什么要这么去搞?我们带着这些疑问的话,然后进入我们今天的课堂,对吧?首先我做一下自我介绍, 我是抖音直播 java 架构思课堂的 king 老师, 大家可以称之为我 king 就可以了。然后我们所有我在抖音直播上的所有的课全部都是免费的,也就是说免费跟大家分享我自己在实际工作当中的一些工作经验, 或者是一些项目设计,或者是一些开发的一些相关经验。目前的话是在一个教育行业的互联网公司担任加瓦加公司一职, 大概的话也有十余年的这样的开发经验。有个人自认为啊,已经有相当丰富的这个项目设计和这个开发的经验。呃,这十来年的话主要就是 专注于这个加纳语言的开发,另外的话对熟也比较非常熟悉这个分布式的架构的设计的一些特点和这个微服务架构的一些设计, 我们对这个微服的一些拆解呀,是吧?对项目的一个服务化呀,微服务的一些拆解,或者是从业务的角度,或者是从技术的角度,然后我们怎么去搭建服务,怎么进行拆分,对吧?这些的话都我们在后面的话都可以进行一一的交流或者是分享。 另外的话对高并发这一块,因为我们在实际公路当中的话都会用到高并发这一块,并发编程嘛,对吧?为了让我们的数据或者说让我们的业务更加顺畅,或者说响应时间更快,更加服,呃, 可以这个有效的服务于我们的客户,然后我们肯定是要在我们的实际夜幕代码的中写那个 关于并发编程的一些相关代码,对吧?如果你现在所在的一些公司或者说根本就没有用到这个并发相关的一些知识的话,那么你可以在二三月份的时候你可以考虑一下跳槽,然后换一下公司,对吧?换一下公司, 因为如果你只是在某一家公司只是展示 crud, 或者说写一些简单非常简单的业务逻辑的话,那么对你或者是对你以后想继续在 java 这个语言的领域里面继续深造或者是什么,那你 相当于你把很大一块的这个家哇他的一些优势全给抛弃了,对你以后的这个唇膏技术这块的话有很大的 影响,所以我建议什么呢?如果你的公司没有搞过,或者说你实际业务当中你也没有去思考过,没有写过 这样的一些并发编程的一些相关代码的话,那么你建议你在二三月份的时候,你可以考虑一下换工作,然后换一下公司,换一下这个互联网的工作,换一家这个 呃,团队比较庞大一点的,然后自己的这个项目,呃自己公司本身里面要用到这个分布式一些叫,或者一些这些互联网目前比较流行的微服务架构,对吧? 学一下这个新的,学一些新的架构,学一些新的这个知识,丰富一下自己的技术,对吧?你比方说你现在挣六千块钱,如果你有了这个边防边城的能力或者是什么呢?你跳一条公司,可能你的月薪有可能就达过万, 对吧?一个家公司现在岗位的基本上也是在五十万,年薪五十万或者到七十万甚至一百万,对吧?很高的一个一个这样的一个阶层。那如果你要想达到这样一个标准的话,那么你首先要把自己的基础知识打牢了以后,然后再把这个我们 业务上或者是说我们的企业架构当中经常用到的一些架构瓦微服务知识啊这些东西再去了解哈,然后再有一些团队管理的一些经验,那么你的薪资不用你不用你去想,或者不用你去考虑,也有可能有人自动去挖你这个能人啊,对吧? 所以我们就是说如果没有这方面支持的话,大家一定就是说可以考虑跳槽或者换一家公司,那换一家公司或者跳槽的时候必然会遇到一些面试一些相关的知识,那我们 今天讲的这个哈士卖部有基本上或者是说大部分的一些互联网公司,或者是一些有相关经验的都会去面拟或者 通过一些面试题来了解,你对底层 java 这一块圆码的一些了解,一些算法的一些了解,一些顺序结构的一些了解,对吧?我们一个哈奇 map 都可以问你很多问题, 所以说我们为了这个,即使我们为了应补面试,是吧?我们也要去去认真的听一下今天的课堂,对吧?认真听一下今天的课。 然后呢?我个人的话,在服务化这个基础架构这一块和这个微服务架构这方面的话,都有一些相当大量的一些设计和开发经验。因为我也有干了 十来年了,大大小小的公司我都干过什么?小公司十个人的团队,三个人的团队,创业团队、百人团队到以及现在的千人团队,对吧?我都都做过。而且我从外包公司到互联网公司的话, 外包公司也干过什么?那种现在的这种互联网做企业的自身产品的这种项目型的团队也做过,对吧?特别是在外包公司的时候,个人的压力比较大,因为那人家就是说相当于是你 你目前的这家公司要让你拜托到其他公司去工作,到那以后你就要去干,然后你就立马就要去上手,他没有给你学习的时间,对吧?所以说在一个外包公司的时候,一个人的压力是特别特别大的。但是呢,我个人认为,那什么在个外包公司的时候,可能 对你的技术的提升会有一个非常好的一个非常非常好的一个这个优势,就是说你有压力,我必须要,而且要客户需要我很快的把这个问题给你解决掉, 那我就需要很快的去熟悉项目的这个业务体系,用了哪些技术,我要很快的去搞,对不对?这需要有一定的经验的人才能搞。如果你刚毕业或者说工作一两三年,那么你要去面试一个外包公司的高级工程师或者是一个架构师的岗位的时候, 特别考验你的这个技术和这个应变能力,一般至少也得工作几年以后,然后你才有可能去这样有挑战公司的去去去,去面试。另外的话,我我个人在做这个呃技术分享的时候,基本上 啊,每周六,也就是说每周六的晚上十,呃,七点半,然后呢都会通过咱们的抖音的直播平台和大家做一些技术的上的一些分享,主要是关于加瓦语言开发这一块的一些相关的 啊技术讨论。然后呢,我在周一或周五的时候,因为我个人也上班吗?我会在周一周五的时候抽取一定的时间写一些关于 java 的一些 ppt, 或者说 java 技术讲解的一些案例也好,或者是呃场景的解决方案也好,或者是 vivo 的一些相关的一些呃,支付点也好,对吧?还有一些开源的框架也好,都会在呃周六的时候和大家进行分享啊。 然后呢,我们回到今天的课题,今天的话我们主要是讲这个哈奇 map。 首先呢,我刚才也问了大家 有没有在二三月份的时候,我们搞这个去面试或者是跳槽,想让自己呃得到更高的这个报酬,月薪过万或者是是年薪百万,这样子对吧?有没有? 如果有的话,大家可以扣个一。那么虽然你面试的是高级岗位或者是架构师,那同样的,你去一家公司去面试的时候,人家也不知道你是一个什么样的水平,人家肯定也会去面,从基础去面你,对吧? 从基础面积慢慢的,慢慢的,然后再往深里去面,就一个哈气 map 就可以问我 n 个问题,同样,因为他设计的点太多, 他涉及到数据结构,涉及到算法,涉及到一些隐含的问题,或者涉及到他使用当中需要避免的一些问题,都需要你去考虑。如果你要是一个高级或者是不高级岗位,或者是要面试一个高级岗位的话,那么你对这些点肯定是熟了再熟 对不对?熟了再熟,比普通的工程师肯定是要了解的更深的,你不仅要了解他的数据结构,不仅要了解他的算法,还有还考验的是你对他的圆满的 了解程度啊,因为现在面试一些高级岗位的,基本上大家都会问一些源码,一些相关的知识,但是呢,问源码的时候呢,哈奇那个一般都跑不了,一般面试官也有可能会问你是什么呢?哎?你读过加号啊, 什么呃?关于哪一方面的一些源码吗?人家可能会这么问,人家不问就直接问问你什么哦,你了解这个 加啊,这个哈西 map 的一些原码吗?你了解这个哈西听过的一些原码吗?人家可能不太清楚你这个具体的一个层次到了哪里,人家可能这么问,那你就可以围绕着面试官这样说啊,我看过这个哈西嘛,哈西 map 的一些相关原码,我们看过这个 spin, 呃,随便用的一些原码,我看过这个随便部子的一些原码,对吧?那你就可以这样讲,然后呢,面子官就可以针对你所提问的这些问题呢,回答的这个答案呢? 然后再深入的去了解你。比方说哦, happy map 是吧?那 happy map 的话,哦,那你可以给我讲一下 happy map 的它的数据结构啊,或者是算法是什么样的吗?可以吗?对吧?然后呢,人家在一步一步 不了解你到底了解或者是熟悉的程度是什么样的,他充分的可以通过一个哈奇马宝了解你对哈奇马宝他原码本身的一个分析能力,对吧?分析能力,使用能力, 还有这个在业务当中,实际业务场景当中针对一些问题的时候,又如何去避免的,对不对?如何去规避的, 我一下子我就可以考验出来你三个点对不对?是不是?所以呢,我们就啊,为了面试我们也很 好好的就是说了解一下哈奇迈巴,这是非常有必要的,也是在业绩当中经常问的,一个一个容器,一个一个纯属对象,对不对?然后呢,我们学习哈姆的迈巴的话,其实也就是主要围绕 的两个点,刚才也说了,我们主要围着两个点去学习哈奇爸爸就可以了,一个就是他的数据结构,一个就是他的哈奇的一些算法,还有数组坐标,数组坐标的一个定位的一个算法,他是怎么玩的对不对?还有他的一个扩容机制 要怎么怎么搞的呢?对啊,我们为了减少这个列表的这个长度的话,他肯定是要进行扩容的,对吧?那扩容的机制是怎么玩的呢?他是怎么搞的呢?所以这些点的话,基本上就是哈奇抹布它里面最为重要的,也就是说我们应该去学习的东西, 他的核心,他的设计思想是什么样的?首先呢,他的一个数据结构,数据结构的话,大家人家面试官会肯定问你啊,他数据是什么样子的,那我们是不是就 可以很流畅的告告诉我们的面子官啊?拍击 map 是由速左加链表加红黑速,对吧?这样一个速记结构完成的, 特别是什么呢?红黑素的话在 g d k 八的时候才出现的,然后 g d k 一点七之前或者 g d k 七之前是没有红黑素这个数据结构的, 对吧?这个这个区别点的话一定要答出来,对吧?你答这个数据结构的时候,不要直接就告诉那个面子官啊,数组加列表加红黑素, 哦,那人家说我去之前可没有听过会员数啊,或者说人家那个公司目前这个面子边的话,他对这个东西不知道呢,对不对?如果你把这个点给他凸出来的话,是不是也是一个亮点,或者说也是个加分项啊,对吧?所以说 哈西外婆他的数据结构基本上就是说数组加列表,那他为什么后面又加,就是说把红黑素给加进来了呢?对吧?他把红黑素给加进来呢?他什么时候会形成这个由数组转换成这个列表的数据结构呢? 那他又什么时候了又从这个从列表的结构转换成这个红黑素的数据结构呢?对吧?这有三个疑问点, 那他扩容的方式又是什么样子呢?对吧?面试官可能围绕的这一个哈奇麦克的话,下面一下子一二三四啊四个问题都给你给你罗列出来了,你怎么去回答呢?那这些的话是不是我们只能是通过原码来去分析,去了解,去看 看一下人家到底是怎么玩的,对吧?看一下奥瑞公司,奥瑞扣公司,不对,奥瑞扣公司的话,他的最后一个版本是多少啊?大家有没有知道? boringco 最后一次最后一个版本就是加了七了,一点七了,加了八的发布的话是由散公司发布的啊?不是啊,说错了啊。 呃,反过来了,说反了,嗯,对吧? live 公司收购以后呢,就是发布了这个加二八的一个版本啊,加二八的一个版本, 然后呢,我们这个里面还涉及到一个点是什么呢?在我们的数组结构转换成像这个断面结构转换的时候呢, 会发生这个哈西冲突,对吧?什么是哈西冲突呢?冲突的话就是什么呢?我们一个元素啊,我们初始化一个哈西麦克的时候呢? 初期初始化,我们的你有一个哈奇 map, 对吧?他会进行初始化,初始化一个十六 十六个长度的,十六个长度的这样的一个数组,对吧?当他发生哈气冲突的时候呢?也就是什么情况会发生冲突呢?假如他这个是零啊,这是零,这是一,这是二。 我们有一个元素是什么呢?有一个 note 节点,这个 note 元素的话,当它这个本身它这有值,本身这个二呢?这个位置的下边位置是有值的,本身有值的。如果我们的哈机子我们又存了一个, 那答案,那么二的话,正好和这当前的这个 note 节点,他计算出来的这个哈七值和坐标,对吧?宿主定位的这个坐标的话是相同的,那么这个时候呢?我们就发生了什么呢?就认为这叫哈七冲突。 当哈西发生哈西冲突的时候呢,我们的这个数据结构呢?就会发生变化了啊,这个节点的话就发生变化了,他就会 插入,就是说形成一个这个链表的数据结构,在他的 nice 的节点上呢,关联下一个 no 的节点,下一个 no 节点,形成链表的一个数据结构, 对吧?形成内面的一个数据结构,他的一个过程的话基本上就是这样子的,那在里面的话其实有涉及到了很多很 很多的一些参数,对吧?他的海底 map 里面的话,涉及到一些很多的一些参数。首先我们可以了解到是什么呢?他的初始化容器的大小啊,初始化数组的一个大小是十六, 那为什么会设置成十六呢?我们不设置成十五、十四或者是十七、十八,或者是更大的,对吧?这样的问题的话,一会后面的话我们都会去讲。另外的话,他在转换成这个由速度转换为链表的数据结构的时候, 他会无限的这个店面结构会无限的扩张吗?或者说变长吗? 会吗?他什么情况下会转换成这个红黑素呢?红黑素呢?而且是什么,为什么要加入红 红黑素呢?是不是转化成红黑素啊?由列表结构转化成红黑素啊?他是当他的列表结构列表长度呢, 达到这个八,也就是说列表长度等于八的时候呢,就会向红黑素进行转换,向红黑素进行转换啊, 然后呢我们玩这个的话,我们可以看一下这个,我们看一个这个哈气冲突的一个现象啊, 什么时候他的这个哈西冲突是一个概念是什么呢?我,我们为什么?我们为什?特别是这个,我们为什么要划这个?这个加八的时候加了一个红霉素? 首先我们看一个菜,看一个这个,呃,我事先准备好的一个视力,或者写了一个加号代码,咱们咱们对比一下啊,体现感受一下他的感受是什么样的?首先我们看一下这个,这个视力,这个用的哈西这个类, 这个例的话其实很简单啊,很简单。那首先这一块代码呢?我们先不看,我们只关注这个慢方法里面就可以了。 这个慢方法,这慢方法里面的话其实很简单,我们声明了一个 map 的一个对象,声明了一个哈奇 map 的一个对象,另外的话我们声明了一个历史的对象,历史的里面的话,我们存了就是三个元素啊,三个元素,三个,三个元素,三个死定了,一个对象有 a、 a、 b、 b、 c、 c, 我们,呃,下面的话,我们是对这个历史对象进行一个便利,分别打印出来这个,呃, string 的 一个哈西值啊,每一个元素的一个哈西值,他会出现一个什么情况呢?是这样子的,我们看一下啊, 我们执行一下,我每次开直播的话,我的电脑就运行特别慢,大家可以稍等一下, 你看他的发音值是什么样的?你看三个三个元素的话全是二幺幺二,二幺幺二,二幺幺, 那为什么他的哈西词全都是一样的呢?这种情况就会出现一个什么样的问题呢?我们把这个三个元素分别存到这个 map 的时候呢,就会产生一个什么问题呢?就是哈西冲突,就刚才我们讲的这个什么呢?哈西冲突 一个问题,太极冲突,就这个 note, 你比方说刚才这个点的话是 a, 那后面这个点的话就会 b b, 然后再后面那个就是 c 井号, 他会产生哈机冲突,哈机冲突的时候他的数据结构就会发生变化,由速度转换成链表 啊,怎,怎么教会大家记住一个点是什么呢?它什么时候是 由数组向这个列表进行转化呢?就是当他的元素的哈七值产生哈七冲突的时候,就会发生数据结构的变变化,大家就大家记住这一个点就可以了。 好,另外呢,我们看完这个以后呢,我们再看另外一个类, 这个类的话是一个,这个类的话是 r v v s, 呃, r s race, 然后 linked 就是什么呢?一个我这里面呢声明了一个顺序结构,也就是说一个副组结构,我们的呃 a 的意思是什么?是什么?什么样的顺序结构啊? 二、例子的话是一个速度结构,对吧? two 那个 ink 的另一个 list 是什么?是一个列表的一个数据结构, 六秒的一个数据结构。然后我们这里面的话就是对比一下,我们来做一个对比,就是什么呢?我们这里面呢要初始化一, 一个 n 等于五万的这样一个元素,我们分别把这五个五万的元素呢放到一个,分别放到一个 l list 里面,再另外分别放到一个这个另个 list 里面。 然后呢我们针对这个历史的呢和这个啊。二、历史的和这个令克历史的,也就是这两种数据结构,一个是数组结构,一个是这个列表的数据结构。我们分别打印一下他的耗时时间,对比一下他的性能。 来我们看一下,我们现在执行一下这块代码,上面这块代码就是一个构造的一个过程啊,构造一个这个 art list, 构造一个 link list。 首先我们看到第一个结构已经出来了啊,按历史的,他查到这五万条五万条数据的话,他号 是耗了多长时间啊?十毫秒就耗了一个十毫秒的时间。然后另一个历史的呢?他他的这五万条数据呢?他耗时多长时间?耗时了五千九五千四百九十五毫秒。 一个是一个,一个一个是后,这这个这个他的倍数,或者说他相差的这个倍数的是不是非常非常明显, 对吧?说明一个问题是什么呢? our list 是不是?也就是说 our list 也就是速度结构的话,它在查询方面是不是特别特别快?然后 link list, 也就是说它的列表数据结构, 他的查询速度是什么呢?如果数据元素过多,比方说五万、两万、十万,那他数据量过大的时候呢?他链表形成的链 面表结构都会特别特别长,对吧?他形成的这个面表结构的话,就会特别特别长, 那他的查询速度就会慢了,通过刚才我们这个例子呢,就可以看出来。什么呢?就可以看出来。 另一个例子的就是说列表数据结构要比 link, 呃,要比这个速度的这个数据结构查询速度要慢很多,不是慢了一点半点,对吧?慢了上百倍, 这就是什么呢?以前那个 hike map, 我们就可以再再回过头来,我们看 hike map 的数据结构,也就可以明显就可以感受到了。什么呢?如果我们往 hike mail 里面 style one 的元素,那请你可以想象一下,我们要查询某一个 healthy 冲突,产生冲突的 元素的时候,那他的财运速度是不是特别慢了?所以说孩子爸爸在加二八的时候呢,加入了红黑素的一个结构,红黑素的一个数据结构来降低这个链表链表的一个长度, 对吧?他列表短的话,其实他的产品性能还是还是可以接受的。那为了讲降低这个降低他的列表长度呢?当他的列表结构啊,当他的列表结构大于八的时候, 也就是说他的列表结构大于八的时候,列音表结构长度啊,等于八的时候,大于八的时候,他的 他就会由链表结构向这个红黑素的这个碎结构进行转变啊,就会转向这个进行转化。 我刚才只说了他这个红黑素转化的一个点,对吧?只说了一个什么呢?他的这个辨别结构长度达到八以后呢?就会转换,那还有没有其他的隐含点呢? 首先大家对这个红黑素这个数据结构清楚吗?其实红黑素呢,红黑素就是一个二叉数啊,对吧?他就是一个二叉数。 m a 数呢,就是一个二差数啊,而且是一个什么呢? ok, 而且它这一个是什么呢?乌黑术 它就是一个 ipad 数,对吧? 他就是一个 art 柱,而且是一个非平衡的。那红黑素素大家都应该知道什么样的素是查匀速度最快的呢?什么样的素查匀速度最快啊? 那肯定是平衡的呀,就是说左右两边长度一样,对吧?左右两边长度都一样,然后这样的速速的话,长语速度最快。但是刚才听老师为什么你说啊,这个红黑素的话,他是一个非平衡的呢? 为什么是一个非平衡呢?他不用直接用这个平衡速呢,对吧?你不是说平衡速度很快?哎, 那这个分公司或者奥瑞国公司这个开发人员,程序员是不是脑子有毛病啊?他不会用用那个,用那个平衡呢?当然啊,各有 有利弊,他也是采用了这个折中的一个方案,红黑素的话,那个平衡二大数,如果你要想保证这个着肉两边他的 长度都是一样的,对吧?他的长度都是一样的,那么就会有一个问题,是什么呢?有一个问题叫旋转啊,竖的旋转, 有一个数的旋转,那这个数的旋转过程呢?就会有一个什么呢?就会特别。