今天来给大家分享一道面试题, res 集群数据,哈西分片算法是怎么回事啊?啊?那我这边给大家整理一个笔记啊,那其实,呃我们上一个面试题就讲到 res 集群价格大概是怎么回事啊?那呃关于呃我们 呃这道面试题啊,史上主要是考大会就是关于比方我们在集群架我下面,我们执行一条命令啊,这个数据,比方 set 啊,图林啊,诸葛你执行这么一条命令啊,我们这个 k 啊,他到底是放在 我们集群里面?不是有有数据是分片存储的吗?那我这场命令里面这个 k 和 value 他到底是放在哪个节点上面去的对不对?这这边有三个节点,他数据是分片的,那我这场命令里面的 key value 到底最终客户端执行了之后他会往哪个节点上面去放呢?他主要是考察这个东西啊,那这里面实际上他会有一个 叫做,呃,就是集群客户端的一个哈西数据分片算法,那这里面大伙要知要跟大伙讲一下,就是对于我们 red 集群来说,他会在我们会针对我们整个集群的所有节点啊,他会给我们分配一个叫做逻辑 哈西槽的一个东西,总共的槽位大概有幺六三八四个槽位,在 reds 启动的时候他就会把这个槽位就这个逻辑上面,并不说真正实在的物理上面,他实际上是一个逻辑逻辑上面的一个槽位, ok, 他会把这些槽位 给每个主节点给他分配好,比方说我把零到五千个朝位,我画给这个主节点, ok, 把五千零一到一万的这些个逻辑朝位给这个主节点,然后把一万零一, 一万零一到幺六,对,幺六三八三,这就幺六三八三,我们从零开始了吗?这个这些个逻辑朝位划分给这个主主结点, ok, 他会这么来做。当然这些主结点的划分你也可以自己去 去定义一些规则。这个我们先不展出去讲,你大概就知道 red 在启动的时候,实际上这些个总共幺六三八四个逻辑朝位,他会按一定规则分配给每个主,每个小的主从里面去, ok, 那将来,比方说我们刚说了我们要设置一条命令,比方 set 图宁诸葛,那这个命令到底 读你诸葛,我要怎么把这这里面的命令啊?我,我这这里面的 k y 六,我最终是,呃存在哪个小的组成里面去的?那这里面有个算法叫哈西分辨算法,其实就我们说的朝位定位算法啊,他会对我们这个 k 啊,就是你这些执行命令的那 k 做一个 c r c 十六的一个哈西算法,得到一个闪电值,然后对我们幺六三八四的这一个,呃,逻辑朝位总数取一个膜,那最终的数值一定是零到幺六三八三中间的某一个值,对不对?那他会 假设你算错了,值是四千。 ok, 那按照我们之前 reds 内部的这个逻辑潮,呃,就分片的一个规则,那你这个数据我们之前在客户端就会算好,干嘛?你应该落到这个主节点里面去, ok, 那最终你在客户端发起了这一条命令干嘛?这条命令会被我们客户端 啊集群的价保里面的相关 api, 干嘛把它发到我们这个节点上面呢?也就你这个 kfin 六,它最终会存储在我们这个主节点上面呢。 ok, 这就我们说的 red 集群,它数据的那个哈西分辨算法, 主要就是这么一个算法,在他的圆满里面就这么实现了。 ok 啊,那这个面试题我们今天就分享这里。那当然我这边还给大伙准备了大概有四五十道啊,常见的一些啊, ready 的面试题 啊,后面会逐一来给大伙分享。那这些面试题其实也是,呃,出自于我这边给他会整理的 java 大数据的一些系统性的一些面试题啊,包括一些复习资料 啊,里面的一一小个章节。那最近如果说在面试或者说在复习一些技术的同学,那大伙如果说需要更多资料,同学啊,想要这些资料同学可以在我们的视频的下方评论区获取啊, 视频配套十万字面试笔记已整理,免费带走!
粉丝2131获赞1.9万

粉丝投稿, hashmap 默认容量到底是多大?很多新手会只回答十六,但这道题的考察点远不止一个数记忆,而是对 hashmap 底层设计逻辑和源码细节的理解。 下面我们一起来看看具体解析。 hashmap 作为一个容器,为了防止内存浪费,那么它一定会有一个大小限制,那么即使我们再去拷这个 hashmap 的 对象,不去指定它的大小的时候,就它的容量是十六。那么如果我通过构造方法去指定容量,假如说指定十八,那么它的粗俗化容量到底是多少? 为了帮大家更系统性的准备面试,我整理了包括各阶段的面试题,加完面试图集,学习路线以及精选的简历模板,需要的是粉幺二三双手奉上。是十八吗?我们可以通过原码去看一下,如果设置十八,那么它的容量到底是多少?这个也是一个粉丝真实的一个面试题。 好,我们可以进去看一下,他有一个关键的方法,什么方法叫做 type size four, 这个方法是去决定我的一个初步化的容量的。好,我们可以去看一下,为了性能,它里面用到了很多的位运算,那么假如我传进来的是十八,那么通过这样一个方法,那么得到的结果到底是多少呢?好,我们可以把方法考过来,我们来看一下。 好,首先我们可以看,假如说传进来的是十八,那么这里得到的结果是十七。好,那么十七往我们的右边去移动一位,然后再进行或等于的运算。 好,那么首先我们得到一个十七的二进值,那么到底是多少呢?好,我们可以来看一下。十七,那么他的二进值是零零零幺零零幺,这是我的二进值,然后接下来再往右边移动一位,那么得到的二进值是多少呢?也就是零零零零。好,幺零零零, 再进行,或等于运算,就是我去先货运算,然后再把这个值复制给我们的 n, 货运算只要为一的地方,那么就是一。好,那么这两个二进值,你看我们去货运算零零零一。好,一零零一, 那么这一个我们再转化为实进值,看一下,零零零幺幺零零幺,可以得到他的实进值是二十五,所以到这一步,你发现他到了二十五,然后再接下来二十五,这一个二进值,再往右边移动两位,那么得到两位零零零, ok, 幺幺零,这个是得到往我们的右边移动两位以后的一个二进值。好,再或等于,那么得到二进值是多少?你看只要为一,就是一 幺幺幺幺幺,这一个二进纸,我们可以去看一下他的二进纸,结果是三十一,再往右边移动四位,那么就什么我去把四位零零零幺 零,对不对?好,零零零幺,这是往右边移动四位以后的结果,那么得到的结果同样的可以看一下,或等于以后,那么是多少就是零零零幺。好,幺幺幺幺, 还是三十一,对不对?还是三十一。好,你再往右边移八位,移十六位,因为移八位以后,他得到结果都是零了,都是零, 那么货运算以后,那么他的结果是不变的。好,你看还是三十一,对不对?好,你再往右边移十六位,那么还是零, 你得到结果还是什么?三十一,所以这里你看到这里最终的结果就是三十一,如果说你看 n 小 于等于零,如果 n 小 于零,你看不小于零嘛?三十一好,他肯定不是一对不对,他也不大于他的最大值,所以得到的结果就什么?就是 n 加一,也就是三十二, 所以我传一个十八的一个出手花容量,但是我们的底层其实会怎么样?取到一个三十二, 那么就是去取我传进去的值,往上找到最接近的二的密,比如说你十八向上最接近二的密,也就是二的五次方三十二,如果你传的是十二,那么就是默认就是十六, 如果传的是十六,默认还是十六,对不对?好?那么这种设计的目的就是要确保我的容量都是二的密,保证在计算下边的时候他的一个性能以及降低他的哈希数值,并且保证在添加数据的时候呢,不会去超过我的数值长度,那么这个就是需要关注的一个细节。

今天来给大家分享一个真实的面试题啊,就是京东一面的,就怎么样用 reddit 来统计用户的访问量?这个问题呢,其实比较简单啊,就是我们的数据类型的一个使用场景 啊,那么在 reddit 里面啊,我们去统计用户的访问量呢,主要可以有三种形式啊,阶段的面试题加本面试突击学习路线以及精选的简历模板,需要的小伙伴已关六六六,我发你。第一种是哈希,第二种呢就是 bitcode, 而第三种就是我们的概率算法叫 hide log。 ok, 我 们来看一下每一种它的优势跟缺点在哪里?那么首先呢,哈希哈希的话呢,其实就是把我们的访问数据啊,以一个 keyfield value 的 形式呢去保存啊,那比如说对吧,在某一天啊 啊,柠檬二七对吧?然后呢,我的一个啊,用户 id, 然后 value 呢,我可以随便啊,一也可以,二也可以都行,因为我只要去统计它的小 q 的 数量就可以了。 那假如说现在零八七,对吧?就是当天啊,那么我有两个用户访问,一个幺零,一个幺五,那么我可以去通过啊,他当天的一个长度,然后去拿出来。那么这个方式呢,就是简单,对吧?比较容易实现,查询呢,也比较方便,数据呢准确性也比较高,但是有一个缺点就是他占用的内存非常多, 呃,然后 key 越多的话呢,它的性能也会下降啊,因为你它是通过哈希嘛,对不对?那么哈希的话呢,就会导致它的 key 会很多很多很多啊,那比如说像拼多多这种,对吧?如果素一级的 pv, 那 么网站呢,就是 reddit 肯定是扛不住的。好,所以我们接下来可以用第二种啊。第二种呢就是 bitset。 bitset 呢,它是通过喂图的方式啊,就是它有一个 xashiv 的 intl 型啊,然后只记录 id 存不存在就可以了 啊,然后转化为二帧,那比如说啊,我现在,对吧?一零一一呢?就是我通过一个用户啊, id, 对 吧?假如说是一,那我在它对应的位置去把它标记为一就可以了啊,然后接下来,对吧?三四六七, ok 啊,那么把它对应的位置去把它标为一就可以了,就是对应的位图 就是它的位置 b 的 位,然后去把它标记为一,一的话呢,就是已经访问了,对不对?好,然后你看 reis 呢?就是,呃,通过这样子的方式啊, 就是可以去做,对吧?你看通过 setbit, 然后一个 key, 然后幺幺幺幺,对吧?这个代表是我五个一的用户啊,就是他访问了,对不对?好,那么然后我怎么去拿呢?就通过 getbit, 对 不对? getbit 我 去拿,看看它是否存在,是否已经访问过了。好,如果我要去统计访问量,我可以通过 bitcount, 那你看,假如说这里面那就是 setbit 两个,那么就代表有两个人已经访问过了, ok, 好, 那么这种方式呢?这样的内存啊,比较小,因为当我的数据量比较大的时候,这样的内存比较小啊,查询呢,也比较方便,也可以去指定某个用户是否已经啊访问过了,对不对?但是也有个问题, 就假如说我的数据量比较小,但是我对应的一个位置,那 bit 位,我就把它设置为一 啊,那么假如说这个位,对吧?你看前面,我这里面标九为一啊,那我就需要维护这么大的一个长度,前面都是零,对不对?好,所以对于啊,非登录的用户,可能不同的 key 接收到同一个 id, 好, 这是它的一个问题,对不对?就可能会存在 啊,就是一个额外的开销啊,但是呢,如果用户非常的稀疏,那么占你的内存可能比方法一更大,就像我刚刚讲的,就是他对应的位置啊,如果比较大,前面的都是零,那这个东西就比较稀疏嘛,对吧?我用户比较少,但用户 id 比较大,那么我需要去预分配内存, 预分配内存,那么这个就可能会干嘛?就是有一个更大的问题。 ok, 好, 第三个就是概率算法,概率算法呢,它只是存一些概率相关的数据, 呃,所以它占用的内存是非常非常小的,但是有个很大的问题,呃,就是它可能会有误判问题,对啊,就是有误判误差啊,它通过 pfa 的, 对不对?然后你看某一天,然后呢,这是我的一个运货 id, 好, 我可以放进去啊,放进去以后我可以通过 bf 啊, bfcount 我 去统计出来,这也是可以的。但是呢,我刚刚讲了,因为它占用的内存比较小, 它存的不是真实的数据,所以它可能会出错。那不管你是 count 也好,还是说去判断某个用户是否已经访问过了也好,都可能会有问题。 ok, 那 么这个呢,是在 reddit 里面啊,去统计用户访问量的三种方式 啊,那么这个呢,就是在呃我们 reddit 里面啊,通过,呃这三种方式啊,可以去统计我们用户的访问量。

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

今天我们来聊一聊已知性哈希算法。已知性哈希算法呢,在面试的时候是经常会被问到的, 而在我们的很多的一些源码设计里面呢,也会用到。为了帮大家更系统性的准备面试,我整理了包括各阶段的面试题,加把面试图及学习路线,以及精选的简历模板。需要的小伙伴你关六六六我发你,比如说我们的哈希 map, 对 吧?这样一个数据结构, 那么我们先来看一下,就是呃,一次性哈希算法。之前呢,我们来看一下就是取模算法。呃,取模算法其实就是我们哈希 map 里面啊它的一个方式,那比如说我们存储数据的时候,会以哈希表的方式去存储 kv 结构,然后这个 key 到底到哪一个节点呢?我们会去通过取模的方式,然后算出在哪个节点 这种方式呢?它会有一个很明显的问题啊,就是啊,当我的节点增加或者说减少的时候,它的映射关系它会发生变化,那么这个时候我需要把所有的 key 需要重新去映射,那么其实就是我们 hashmap 里面经常被问到的 啊,像扩容,对吧?那这块怎么解决的? ok 啊,所以呢,他的迁移代价他是比较大的,那么一次性哈希呢,就是优化这种场景的,那么他的工作原理呢?其实比较简单啊,首先啊,一次性哈希他是通过哈希环的一个数据结构来实现的,这个环就是 in tag 的 最大值零到二的三十二次方减一, ok, 好, 然后接下来他会把节点,然后通过一个哈希算法,以后呢,在哈希环上面去确定一个位置,那比如说现在我有三个节点,那么在哈希环上面会有三个位置好,然后接下来同样的我的 key 放到哪一个节点,我也会通过哈希算法会得到一个哈希值, 那你要假如说啊 k, 对 吧? k 一 啊,然后呢会通过它去算法啊,落到这个节点, k 二呢?落到这个节点,对吧?然后 k 三,就是落到这个节点, ok, 然后这个节点到底放到哪一个真实的节点里面去呢? 那就是放到哪一个 mod 里面去呢啊?就是会顺时针向下啊,找最近的哪一个节点?比如说 k 顺时针,最近的是 mod 一, 放到 mod 一 好,然后 k 二顺时针,那么最近呢是 note 二,放到 note 二,对不对?然后 k 三顺时针,就是 note 三,放到 k 三,然后放到 note 三, ok, 好, 那么这个就是我们的一次性哈希, 那么一次性哈希有什么好处呢?它一个最主要的作用就是能够去减少我的数据迁移量, 假如说我现在加一个 note 四,那么其实影响的那么只有 note 一, 就是我把 note 三到 note 四这样一个数据区间,那么我可能放到 note 四,对吧?原来是放到 note 一, 现在我只要放到 note 四, ok, 那 么这个就是受影响的范围 啊,原来我是需要所有的需要重新算,现在我只需要切弄这一部分数据就可以了啊?啊,那么这个呢,就是一致性哈欠啊,他带来的一个很最主要的功能,那其实呢就是我能减少我对数据的影响,在扩容缩容的时候,但是他也会有个问题,就是数据分布不均的问题 啊,因为你这个 node 节点,对吧?就是 node 一、 node 二、 node 三、 node 四,它不是平,平均分配的,它不是平均分配的,那它可能在任意一个节点,那么有可能,对吧? node 一 跟 node 三它接得很近,挨得很近的话, node 一 它承受的数据量就很少, 对吧?就很少。所以它有一个数据倾斜的问题,包括在这个节点之间,对吧?它有一些可能热点数据也会导致一个数据倾斜。所以在像 readcast 里面啊,它就引入了虚拟节点的一个概念, 就虚拟节点就是这个节点,他不是个真实节点,那而是一个虚拟槽,虚拟槽我再跟真实的节点去绑定,那我就可以很灵活的去分配我的数据分配到哪个节点去了。 ok。

一口气带你刷完数据库,知识点、高频重点、深度解析!大家好,我是专注伽马干货分享的灰灰。我们都知道 mac 的 存储引擎里面支持两种常见的缩影数据结构,一种是 b 加数,一种是哈希。其中 b 加数是我们日常开发中接触的比较多的, 但是很多小伙伴不理解 b 加数的形成过程,今天我来给大家分析一下。另外啊,我之前的视频内容中留言领取。 要了解这个过程,首先我们得从锁影说起,我们先来看一下锁影它官网的一个定义,锁影是根据我们特定的猎去导航的时候能够非常非常的快速, 如果没有锁影 macbook 呢,它必须要从第一行开始去便利,整个表越大呢,那么开销也就越大。 如果特定的列里面有一个缩影,那么我们能够去快速的找到它指定的一个位置,而不需要去查询所有的表数据,这样子的开销呢,要比我们每一行一行的去迅速的去搜索要快很多。 那么这个呢,是 my sql 官网对于锁影的一个定义,所以啊,锁影呢,是根据某个特定的列去查询数据的时候,能够去加快查询性能。这个特定的列是我们在创建锁影的时候是去指定的,那比如我们去创建锁影的语句 create index, 所以名字用什么数据结构,然后在哪一个表,然后后面我们发现他要去指定一个列,这一个列就是我们去根据快速去查询的一个特定的列,你根据什么列去建立,所以那么我根据这个列查询的时候呢, 就能够非常的快速。为什么能够提高我们的查询性能呢?在我们之前的一些视频里面,我们分享过,我们所有的行数据啊,都是放在页里面的,那比如说我现在有一个很简单的表, 这个表呢就是 word teacher 表,然后它有几个字段, id、 名字、年龄以及地址。那么这些数据它是怎么放在我们的页里面的呢?好,我们来看一下一个图, 我们的横数据啊是放在页里面的,页大小呢是有限制的,所以啊,我们表的数据是会分散到不同的页, 并且为了能够更好的范围查询以及页类数据搜索默认啊会根据主页 id 进行排序。比如这里面我会有很多的页来保存这些数据, 然后数据它的排序规则是根据 id 来排,然后每个页之间又是一个双向列表,页中间又是一个单列,单列是为了能够更快的在每个页里面查询到我想要的数据,因为现在我们虽然只是每个页里面只有三条数据, 但是真实场景肯定不止三条。那么这样子的话,我们能够去便利数据的时候,我们就需要去便利这个列表。假如现在我需要去找寻 id 为六十八这条数据,我们发现我需要去便利整个列表,需要便利一二三四五六七, 我需要便利七个页。页又是我们内存跟磁盘交互的最小单位,所以在极端情况下面,我们可能需要跟磁盘进行交互七次, 并且随着数据量越大,那么查询的性能也就越来越慢,因为列表的时间复杂度是 o m, 我 们得想点办法去提升我们的查询性能, 那么这个办法就是为我们每个页去创建一个目录,这个目录是我们目录页里面的一条记录,这条记录不会去保存我们完整的数据,只是去保存我这个页里面的最小值,然后页码, 比如这个页最小值是一,页码是十,这一个页最小值是十八,然后页码是十二。这些目录我在一个页里面放的数据也是有限的,因为页大小是有限制的,假如只能放四条数据,其他页的目录我也会新开一个页,这个时候我有两个目录页,那么我也不知道应该去哪一个页里面去查, 所以我会去搞一个根目录。同样的,现在假如说我要去查询六十八这条数据,我会从根目录开始查。根目录六十八,那么我最小的数据是四十八, 所以肯定是去页一里面去查。在页一里面我能够去找到六十八这条数据,一定在四十二这个页,因为六十八是大于六十五的。然后接下来我去到页四十二里面找到六十八这条数据, 所以同样的场景,我只需要遍历页八十八,页一跟页四十二,我只需要遍历三个页,所以它的性能会得到提升。那么这一个数据结构其实就是我们经常讲的 b 加数的数据结构, 它能快速的提升查询性能。今天的视频呢就到这里了,希望能对你有所帮助。我是灰灰,我们下期再见。大家好,我是专注 java 干货分享的灰灰。我们在面试的时候老是被问到主页锁影、聚集锁影、居住锁影很多的名词,那么 excel d b 的 锁影到底怎么分类呢?今天我给大家一次性讲个明白。 另外之前的 excel 程序员求职面试宝典里面有需要的小伙伴可以在评论区置顶中留言领取。 我们先来看一下官网对于缩影的分类。官网对于缩影的分类啊,其实比较简单,它就两种,一种叫 cluster indexes, 一 种是 dictionary indexes。 那 么 cluster indexes 就是 我们经常面试的时候被问到的具体缩影,主键缩影、句数缩影都叫 cluster indexes。 secondary indexes 就是 除了 clustered index 以外所有的,所以都叫做 secondary indexes。 那 么什么是 cluster 的 indexes 呢?这里讲得很清楚,每个音的 d b 表都会有一个特定的缩影,叫做 cluster index 来保存我们的数据,通常就是我们的主键 id 变, 那么如果没有主键 id 列,我们会用一个非空的唯一的列来作为 cluster index 的 排序段。如果主键也没有,也没有非空的唯一列,那么我们有一个或 id, 所以 在 cluster 的 index 里面作为排序的那一个列一定是唯一的。 并且他也讲了我怎么去提升我的性能,其实他讲的比较模糊,但是这个在我们上一个视频已经分享过了,目的是去减少我们的磁盘。 i o secondary indexes, 也就是二级锁影,这个也讲了除了主键锁影以外,所有的锁影都叫做二级锁影。 在二级锁影里面,每一行它包含了一个主键 id 和指定的锁影列,这个是在我们创建锁影的时候指定的。那么这个主键 id 用来干嘛呢?用来去搜索我们的行数据,去我们的 class 的 index 去找, 所以也讲了这里面主键 id 不 能太长,因为我们每一个二级锁影里面都会包含我们的主键,如果你越长,那么它就会占有更大的内存。 主键缩影跟二 g 缩影的区别我们通过官网其实也能讲出来了,主键缩影也就是我们的 class 的 index, 它的字段是唯一的,但是我们的叶子节点会保存我们完整的行数据。而二 g 缩影它只会包含 class index 的 排序字段,以及我们在借力缩影的时候指定的列。如果你需要查询完整的,我们需要通过 class index 的 排序字段去 class index 里面去查询。 ok, 今天的视频就到这里,希望能对你有帮助。我是灰灰,我们下期再见!大家好,我是专注伽瓦干货分享的灰灰。回表和覆盖锁影是我们优化数据库查询的必备知识, 也是面试中啊比较常见的问题。今天这期视频我就分享一下我对回表和覆盖锁影的理解,如果你有不同的意见和看法,也欢迎在评论区留言。另外啊,之前的新业视频内容我整理在了伽瓦程序员职面试宝典里面,有需要的小伙伴可以在评论区置顶中领取。 我们先来看一个场景,假如现在我有一个表叫薄的很六,这个表里面的字段有 id、 名字、价格、标签、图片类型以及总数, 并且我建立了一个缩影,这个缩影呢,是一个联合缩影,由 type 跟 bryce 组成,名字是 index type bryce 这个表里面的数据量大概在五十万左右,五十万零五千八百五十七条。现在我要去查询 type 小 于六的数据, 由于我建立的缩影字段第一个字段是 type, 所以 这个缩写数的排序首先是根据 type 来排,那么小于六它是满足最多匹配原则的,它一定是能够走到缩影的,我们可以去看一下它的执行计划,它走到了缩影 index type plus, 它扫描的数据量只有五万多, 但是我们查询的数据是心心就是整行,包括所有的列。上个视频我们分享过,在我们的 synonyms 里面,也就是二级缩影里面包含我们借力这个二级缩影的字段以及主接字段,那么走到的 index type。 brace 这个缩影树里面会包含 id, type 跟 brace 三个字段,我们查询的是星,也就是所有的字段,那么 name, tag, image, count 字段在我们的二级所引面是找不到的,我们就需要用到我们的 id 回到 cost index 里面去查询我们的数据。根据二级所引里面的主键 id 回到 cost index, 也就是我们的聚集所引面去查询数据的过程叫做回表。比如去查询的不是星,而是 price rise 字段在我们的 secondary indexes 里面是有的,这个时候我们就不需要回表,再看一下它的执行计划,它里面有一个附加类型 extra, 叫做 using index, using index 就 代表我不需要回表了,那么这个场景叫做覆盖锁影,覆盖锁影不是加了锁影去提升性能,也不会去减少扫描的数据的行数, 你看这里扫描的还是五万多,只不过我需要查询的数据不需要再去聚集所影里面去查了,在你的二级所影里面就已经覆盖了你要查询的内容,所以还不如把它叫做所影覆盖。 以上就是我的全部理解,今天视频呢就到这里了,我是灰灰,我们下期再见。大家好,我是专注伽瓦干货分享的灰灰。我们背过很多的八卦文 说范围查询会导致锁影猎失效,耐克百分号开头会使锁影失效,那么今天啊,来给大家分享一下为什么会失效。另外之前的系列视频我整理在了 java 程序员求助面试宝典里面,有需要的小伙伴可以在评论区置顶中领取。首先我们来定义一下什么是 锁影猎,能快速的解锁到我们想要的数据来减少我们的行数,而不需要进行全表解锁。 比如现在我有个表, microsoft 的 六,这个表里面现在的数据量大概在五十多万,假如现在我有个需求,我去查询类型小于六的,在没有建立锁影之前,我们发现它扫描的数据量是差不多是全表扫描,并且它没有用到锁影,因为没有锁影。 假如现在我去创建一个 index type plus 的 锁影,那么创建完了以后,再根据特定的 microsoft type 这个列去查询,我们发现只需要查询五万多数据, 那么这个呢?用到了粘合缩影,它扫描的数据量比之前少了十分之一,这样我们根据特定的 product type 这个列去查询的时候,发现不需要进行全表解锁,提升了我们的查询性能, 这是锁影的作用。反过来锁影失效就是本来有这个特定列的锁影,但是解锁数据的时候不能根据这个特定的列来解锁扫描数据。比如我创建的锁影里面也有 rise 这个字段,但是你再加上 bot 这个 type, rise 的 判断等于五十五。 本来我小于六的数据量就只有五万多了,加上五十五的价格以后应该会更少,但是我们发现它扫描的数据量没变,还是五万多,这一个 rise 就是 缩影,是失效的。那为啥会失效呢? 首先啊,联合缩影的排序规则是先根据左边的第一个字段排,如果第一个相等,再根据第二个排,比如这一个缩影先根据 type 来排, type, 如果相等的根据 rise 来排,假如一二三五六七, 然后一,如果相等,那么四十五十五,二,相等三十五十五,三,相等四十六五十五。这一个数据是满足我们联合所引的排序规则的。那么现在我们根据 product type 小 于六来查询数据,我们发现查到的是这些数据, 但是呢,这些数据里面 rise 这个字段的数据是无序的,因为前面的 type 是 个范围,既然是个范围,那么后面的字段它就一定不是有序的。那么你加上 rise 等于五十五的条件,你发现五十五你不知道在哪里扫描的数据量,还是 type 小 于六的数据量是一样的, 那么这一个就是导致 rise 它失效的原因。判断某一个字段的缩影是否失效,你只要判断我扫描的数据的时候,这个字段它还是否是有序的, 如果是有序的,那么我能走到缩影,如果是无序的,那么这个字段我就不能走到缩影。那么我们经常背的向范围查询是下个缩影列失效,不符合最多匹配原则,百分号开头、类型转换等等,都是因为导致了我这个缩影列里面的数据无序, 但是呢,具体啊,用不用锁影,最后呢还是优化器来决定的。今天的视频啊,就到这里,希望我的回答能对你有所帮助,我是灰灰,我们下期再见!在之前的视频里啊,我介绍过锁影的类型,必加数的形成,锁影失效的原因等等。 我把这些问题的答案都整理进了 java 程序员手册里面,有需要的小伙伴可以在评论区置顶中领取。今天啊,我们接着来讲锁影的相关面试题,说一说什么是锁影下推, 上个视频我们分享过啊,我们建立多个列的联合锁影,第一个列能走到锁影,那么整个锁影是能走到的,但是可能因为不满足最初匹配范围查询等等情况,导致后续的列无法走锁影,也就是锁影失效。例如啊,现在我建立了 edge 跟 name 两个字段的联合锁影, 我们去执行下面的查询的时候, name 是 锁影失效的,查询 snake 等于十三 and name like 百符号开头。灰灰,我们发现啊,如果没有找到缩影,首先查询数据一定是去 excel d b 表里面去查, excel d b 表里面有两个缩影数,一个是二级缩影数,包含指定的两个缩影列,还有 id, 还有一个就是主键缩影数,它包含了完整的行数据, 查询 name 等于十三的数据,以后我们能查到 id 为四根二的两条数据,这个时候查询的是星,所以它需要回表两条数据回表,然后给到我们的 my sql server 去进行 name, 以灰灰一结尾的调节过滤,最终回到一条数据, 这是在没有缩影下推的情况下面,如果没有缩影下推,数据量比较大的时候,假如我第一次查询返回的是十万数据, 那么我需要从英的 d p 返回十万数据给到 server 回表也需要回表十万数据,所以呢,有了一个缩影下推的优化。缩影下推的优化还是刚刚那个场景扫描的数据量,还是同样的是四乘二,因为 name 它是缩影失效了的, 我们发现 name 虽然失效这个字段还是在二 g 所以 里面的,那么这个判断我能不能不要给到 server 去判断,而是在二 g, 所以 里面判断回表。我也不需要全部的数据都回表,而是在二 g, 所以 里面判断以后再回表呢?比如四跟二只有四这条数据是以回回一结尾的, 在二 g, 所以 里面判断好了以后只有四这条数据是有效的,所以把四这条数据给 server, 然后回表也是根据四这条数据去回表。 所以锁影下推是将过滤的步骤给到二级锁影来做,如果它能做去减少回表的次数以及减少跟 server 交互的数据量, 那么锁影下推只会在二级锁影树里面生效,并且我的判断的列在二级锁影里面,有才会去走到锁影下推。怎么去看有没有走到锁影下推呢?我们在看执行计划的时候,可以通过 using index condition 来判断, 如果附加信息里面有 using index condition, 说明它是走到了缩影下推的。比如根据 edge 等于二十八 and name 百分二开头 这一个粘合缩影, name 走不到缩影,但是它会走到缩影下推。今天的视频啊,就到这里了,希望能对你有所帮助。我是灰灰,我们下期再见。大家好,我是出场必有干货的灰灰。今天开始啊,我先给大家分享一下事物的基本概念和起用方式。 另外啊,之前的英纳 db 系列视频全都整理在了 java 程序员求助面试宝典里面,有需要的小伙伴可以在评论区置顶中留言领取。 事务。在英纳 db 里面啊,定义的是可以提交回滚的原子工作单元,在关系性数据库里面工作,无非就是通过搜索语句进行增删改查的操作, 所以通俗点来讲就是把我们的搜索语句作为一个原子单元去执行,这个搜索语句可以是单条。那么怎么开启事务呢?在我们的官网里面其实讲的很明白, 它的开启事务的语句叫 start transaction, 可以 指定参数,比如是否要去开启一个快照,你是一个只读事务还是说是一个读写事务?默认它是一个读写事务。 如果你设置了只读事务,那么在这个事务里面你不能进行增加改的操作。当然如果你不需要去指定参数的话,你也可以用 begin 开启一个 work, 然后用 commit 去进行提交, rollback 去进行回滚。 如果搜索语句它只有一条的话,那么它也会一个自动提交的概念,就是我们经常在开发的时候写一条搜索语句,我们不需要去手动 commit 的 原因,因为一条搜索语句它会自动 commit, 当然呢,你也可以去把它关闭。我们现在来简单演示一下,开启一个事物叫斯坦的 transaction, 那么接下来就是我们的工作,假如我们去更改播放器表里面零加一 id 等于一的,然后呢我再去改一条 id 为十的,我们现在没有提交,也没有回滚。先来看一下之前的数据, id 为一的是二十三, id 为十的是二十九, 那么开启十五以后,我可以去进行回滚,回滚的话就是我所有的更改它是失效的,所以数据不会有任何变更,我也可以同时提交。如果同时提交的话,两个数据同时修改成功, 二十四三十,我也可以进行部分的提交跟回滚。假如现在我在同一个事物里面,我想去提交 id 为一的,但是我要回滚 id 为十的操作,我可以去指定 回滚点,叫 seven point, 回滚点的名字你可以自己定义,比如说叫灰灰,那么接下来我去提交我要回滚,我回滚点之后的,所以在提交之前我要去指定你要回滚,我回滚。这个时候他只会提交 id 为一的数据,而会回滚 id 为十的数据。 我们会发现 id 为一的它会加一,但是 id 为十的还是三十。那么这个 safepoint 也是我们 spring 事务里面,它有一个传播机制,叫窃逃事务的一个实现方式。 以上啊,就是今天的全部内容,如果这期视频啊对你有所帮助的话,请动过小手帮我一借三年,我是灰灰,我们下期再见。

你跟我说一下他看的哈士曼和哈士曼有什么区别?他用的哈士曼,他是现场安全,哈士曼不是。他的现场安全是通过 c a s 和锁匙的滑向。对,但可以更加深入,比如说哈士曼在多型的情况下面可能会出现问题,比如说扩容的时候形成一个滑行列表,导致此循环。而他看的哈士曼从 g t k 八以后呢, 用 c s 加 synchronize 实现了高效的运发。那如果面试官问我具体怎么做的,怎么回答,你可以这么回答,担心你简历上的东西啊,讲不出来。我已经把面试经常问的一些基础站场景题都整理在了两百万字的面试文档里面,里面针对每个知识点啊,都有很详细的一个解析思路, 有需要的可以在评论区查看。当插入一个新元素时,如果目标位置为空,就直接用 case 无锁写入。一旦发生哈气冲突,比如说已经存在列表或者红黑树了,那就对列表的头节点或者红黑树的根节点去加 synchronized 的 锁, 锁的力度呢,更细,这比早期 gdk 的 segment 分 段锁更加清亮,也避免了 hash table 或者说 connection 点 synchronized 的 mic 那种大锁的性能瓶颈。另外啊,康康的 hashmap 呢,还做了很多并发症的优化,比如说扩容的时候,它是支持多县城协助迁移数据的,然后 size 它不加,全举锁 用 base count 加 count cell 分 散统计,然后也不允许浪值或者说键来避免一个歧义。而 hashmap 呢,它完全不考虑并发,追求单县城情况下面的极致性能。所以啊,两者的核心差异不在于是否形成安全,而在于如何实现安全。 ok, 理解了吗?嗯,好。

啊,抖音上还有加袜支付呀。你好。哎,你好,你讲一下这个哈西 map 底层用的什么数据结构?嗯,哈西 map 底层的数据结构,这个在 j t k 一点七中,哈西 map 的底层数据结构是数组加链表, 在 jdk 一点八中,链表这里可能转化成红黑树。嗯,你哈士亮比的这个链表什么时候能够转化成红黑树? 这个这个就当哈西 map 理链表中的元素个数大于八,并且数组的长度大于等于六十四时,才会将链表转为红黑数。嗯,还可以啊,那为什么这个哈西 map 的链表呢?转化的是红黑数而不是平衡二 二叉数呢?这个不太清楚,感觉就是横汇数和平衡二叉数。这种对应健身来说是不是就是有点太复杂了? 嗯,也对啊,那要不讲一个哈西 map 的扩容机制吧。哈西 map 的扩容机制?嗯,这个我知道的,就是如果数组的长度达到初始容量乘以负载因子,再插入元素,就需要扩容操作嘛。 扩容就分为两步,首先就是创建一个新的 ancieno 的空数组,然后长度是原数组的两倍, 其次是,呃,便利原 ancieno 的数组,把所有的 ancieno 的节点重新哈吸到新数组。嗯,那哈吸算法是怎么实现的呢?呃,这个,这 歌也不是很清楚哎,感觉你对这个算法基本上是一无所知啊。我看抖音上好像不是有个扎瓦之父吗?初中学历就可以手写哈奇迈普呀,这个应该很简单吧。啊,抖音上还有扎瓦之父呀。哎,好吧,那就这样吧,拜拜。嗯,拜拜。拜拜。

嗯,好。刚才同学回答的不错哈。昨天昨天咱们留的这个疑问,今天咱们解决一下啊。然后 一个类模板中会有这四种东西,这是前面咱们说过的对吧?对。嗯,一个类模板中会有这种东西,会有这四个东西。那么这个这个咱们其实已经见过了。他们那个修饰的是不是默认都可以继承啊? 这个已经搞定了。其实他们这个修饰的是不是默认都可以继承?对嗯,好。那么咱们来看封装方法。咱们来看成员变量。 也可以咱们来看成员变量啊。刘,假如说 parent 有一个成员变量,金额吧?金额啊,整个整形的。 嗯,你老父亲有多少钱,有多少家产,咱们就说金额吧。好。然后成元变量,根据咱们全边前边学过的知识,有成元变量一般咱们都会怎么着? 会封装,会私有化,对不对?嗯,好。当然如果说这个成员变量封装了,私有化了,在这个类里头能访问到吗? 是可以访问到的,对吧?嗯,在这个方法里头是不是可以访问到的?嗯,好。那么在封装方法里头可以吗? 当然可以了。封装方法主要是为了啥来着?还记得吗? 对呀,主要是不就是为了操作他的值吗?嗯,封装方法你整成 public 的,当然是可以操作成员变量的。来右击写两个封装方法。 封装方法一般是成对出现的啊?封装方法一般是成对出现的,一个是用来获取的,一个是用来 对用来复直的,一个用来塞的,一个用来取的。好。然后在这里头咱们看一下,没有语法错。很明显我是不是可以能操作到重圆变量的 对吧?嗯,那么这个能不能被继承呢?这个能不能被继承呢? 所谓被继承是什么效果来着?只要是比如说这个嗯, 他被继承了。他的效果是说这个子类长子里头没有定义也可以被调用是吧?对。嗯,好。那么咱们来看一下这个私有化的能不能被继承?不能,咱们试试不就知道了吗? 在他独有。他有一个独有的方法。再给一个方法啊。 public void。 这个叫个什么呢?这个就叫就叫 get 金额吧。 他想看看他老爹有多少钱,或者说他想看看他有多少钱,有没有从他老爹那继承过来。为什么给我报错 哦, word 写错了是吧?哎,没错呀,他把那个 word 哪错了? 我看看啊,给我报什么错?哦哦,重写了,我再换个名字啊。嗯, get 查看吧。 嗯,行,好了,回头脚重写了我告诉你我。那为什么错啊? 其实那是一种重载。其实是一种重载。等有重写了我再跟你说。那一块为什么 错啊。好,来看一下啊。这长子。这有一个方法,他想查看一下金额。什么意思呢?意思是说他想看一下那个金额,他老爹有的财产,他有没有继承过来。如果能继承过来,理论上他这是不是应该能看到呀?他想看一下 上衣,这来查看一下啊。如果他继承过来了,理论上他这是能可以访问的,对不对? 要要按咱们前边继承的效果来说,继承过来了,是不是就可以被访问,就可以被调用默认定义了?默认拥有了吗?但是现在看他能访问吗? 他能访问吗?你看他如果说他老爹的这个成员变量定义了, 假如说成员变量私有化,私有化的成员变量被长子继承了,那么效果效果是不是就相当于?这不用写,我也定义了一个成员变量啊,那这定义了,理论上我这是不是应该能访问到呀?那现在看看,我能访问到吗? 能访问到吗?这不是报错了都明晃晃的大红,这不报错了吗?访问不到,那么访问不到。咱们今天就验证了第一个点,私有化的成员变量是访问不了的。 死有化的成员变量是不能被继承的。 seal 化的成员面料不能被 四类继承, 或者说不能被此类访问吧,不能被此类访问。私有化的成员变量啊,不能被此类访问 也不合适。老前辈们这一块就让人整的就很难受,怎么说都不对。嗯,还是用继承吧 还是用继承吧啊嗯,私有化的呈现变量不能被子类继承,这是刚才咱们验证的一点,对不对?嗯,好。那么咱们来想一个问题,那我在给上衣妞对象的时候,创建对象的时候,咱们还记得不?记得我在创建对象,我先把它注 吃掉啊,省的他报错。大家还记得不记得,我在一个测试类里头,我在创建一个对象的时候,我在 new 的时候,这个 new 这个动作会做什么事? 你有对象的时候,我给这个变量分一大块,划分一大块空间,然后这个类模板里头有什么变量,我就 给什么空间,有什么方法我也给空间。还记得不?嗯,我找到那张图啊,来看一下,回忆一下啊,那张图在哪? 嗯, 好。还记得这张图不?这是当时 new 了一个杨天琪 student 的对象,这是当时 new 了一个孟国洋 student 的对象。还有印象不? 在你有对象的时候,类模板里头定义了什么成员变量,然后对象者是不是就得给人家给够空间呀?哎,给足了空间当然有方法,是不是也要给足了空间对不好?那么现在咱们来想这个上衣,咱们来想这个上衣 长子,我在扭长子的时候,咱们来看他的类模板有重现变量吗?没有没有,反正刚才验证的是没有继承过来的是吧?有, 有方法吗?有方法,有一个赚钱方法,还有一个私有金额。查看金额方法对不?嗯,那么最起码我这个对象里头是不是可以有赚钱和这两个,这两个方法是给空间的是吧?是,那那个金额给没给?反正现在我感觉是没给对吧? 到现在为止是不是可以得出这个结论?金额貌似是没给空间对吧?嗯,也就是我这内存里头现在只有我这个对象的。内存里头就是上衣这个这个对象, 这个 se 这个对象里头目。目前我能看到的貌似只有赚钱和查看金额。当然哦对,还有副类呢。继承了这个拜貌貌似只有三个方法对不对?能跟上吧?嗯,这个对象这个对象里头 我现在看到的结果就是有有三个方法。大爱是从老父亲那继承来的,这一是我自己独有的方法,然后我刚才还又定义了一个独有的方法叫 ceo 金额。 现在看到的好像我就能只有这个。我这个对象里头好像只有这三个方法,对不? 李诚信你怎么了?你怎么了?好,那么继续啊。那么成员变量暂且放下成员变量暂且放下。然后咱们来看封装方法 他老爹。那除了成员变量之外,是不是还有两个封装方法呢?对不对?对不对?两个封装方法是 public 修饰的是 public 修饰的, public 修饰的。好,那来看一下上衣。我这有写 封装方法吗?有写这两个封装方法吗?这两个封装方法有写没?没有写对不对?这不是很明显吗?我没有写呀。嗯,那么你们说 s 一能调用吗? s 一点,我晒他一个金额,比如说他有八十块。嗯,鲍鱼法错了吗?没有。哎,邪了门了。方法是啪啪了个修饰,这我能调用,这我能理解,对吧?但是我调用之后,这八十块我给谁呀? 这八十块我给谁呀?我是给成员变量的对吧?那这个成员变量这给的谁?难道给到老爹手里头了?还是给到 se 对象里头了?来,我验证一下 看看我验证一下看看啊,难道给我塞到 s 一空间里头去了?这个方法是不是也被继承了?嗯,因为啪啪这个修饰吗?也被继承了,对吧?好,来,我打印一下看看。 这个是上衣的啊。 s 一的。来,打印一下看看。这八十块钱难道塞到 s 一空间去了? 好,执行一下看看啊。 稍等啊。越来越慢了,就这直行,我都感觉他的直他都 bill 了一分钟。 好,来,打印一下看看啊,快出去。哎,出来了。 s 一 s 一这个对象,我这拼了个祝福串。 s 一对象,他从他的空间里头拿到了八十块钱,正好是我塞进去的那八十块钱是吧? 哎,那有子你得到一个什么结论啊?子类估值不能影响 咱们一开始以为这八十块钱给老父亲了是吧?因为那个私有的成员变了,不是不不能被继承吗?咱们以为 给老父亲了,但是其实没有。这时候有老父亲对象吗?老父亲连个对象都没有,往哪塞去是吧?根本就没有空间。那其实给谁了?其实给了就是给了长子那个空间了对吧?嗯,就是塞到他空间去了。好。所以呢?这有一个说法, 稍微别扭,绕口一些。注意听注意听。私有化的呈现变量私有化的呈现变量。不能被子类继承不能被子类继承,但是可以被子类拥有。什么意思呢?嗯, 但是你可以被子类拥有。什么意思呢?意思是子类创建对象时,子类创建对对象时, 子类创建对象时,副类的。呃,怎么说,别扭的很。子类创建子类创建对象时,也需要也可以。 嗯,怎么说?我想想怎么说啊。这怎么说都别扭。可以被子类拥有。大白话就是说子类创建对象的时候,无论父类有多少个成员变量,子类都是要分配空间的, 子类都是要分配空空间的。子类创建时子类创建时呀,就不能说从负累继承的成员变量子类创建时是是需要 是可以根据。哎,这样说。嗯, 此类创作创建对象时,是可以根据副类的成员变量来分配空间 来分配空间。 ok, 嗯,这样能理解不?嗯,是我是是不能继承,但是我可以拥有。 这好这这就像咱们人类社会中有一条有,有一条那个呃有一条法律条纹是说刘假如说哈那个呃假如说你老爹那个有,有一套,那个有一套房产,然后你可呃不,这个不,不准确。比如说,比如说你老妈 有一套珠宝,然后你可以使用,你可以使用,但你可以,你有使用权,就你平常可以带,但是你没有拥有权。他的所有者还是你老妈 能听明白不?嗯,成员变量别扭就别扭在这。因为成员变量私有了,私有了,所以出了这个类,他又不认了,出了这个类又不认了。所以说,咱们从字面上来说, 成员私有化的成员变量是不能被继承的。私有化的成员变量是不能被继承的。但是呢,但是呢,在分配空间的时候,此类是可以拥有这些成员变量的。 嗯,是可以拥有的。你老爹有八十万的财产,其实你也相当于隐性的拥有。为 什么?因为你可以花,但是那八十万不在你名下。这次更更清晰一些了是吧?嗯,对,私有化的成员变量就是这个德行。对,你不是明面上你,你名下没有,但是你可以花。分配空间的时候,内存也会给你空间。 嗯,如果你需要,你如果说有需要,你存取这个金额,你也是可以动的。假如说你花掉十万,那么这个账,那么你的你的金额里,你的那个账户的金额就只剩七十万, 你也是可以存取这个值的。当然,长子花掉十万,那是长子的。如果说是老二花掉了十五万,那老二是不是就剩六十五万呀?嗯,也就是说,分配空间都可以给,空间都可以给,给了之后就是你自己的事了。你们老 爹一人给了你们八十万的启动资金,剩下的就看你们自己的本事了,自己挣的多金额就多,花的多,金额就少。 听得明白不?嗯,空间分配了之后,那就是对向自己的事了。啊。好,那么这咱们就说完了啊。 这就说完了。好,那么接着再说。私有化的成员变量是不能被继承了。嗯,但是封装方法是可以被继承的,对不?所以在子类他想要,他不是拥有那个空间吗?但是他明面上他又不能去直接通过名字调, 他这通过名字调是不是就报错呀?来看他这不能通过明面调。对。嗯,那他可以通过什么呢?对,他可以通过 从复类那继承的封装方法。嗯,封装方法叫从老爹那继承来的封装方法叫 get 金额。对,他可以通过这个方法来查看。 嗯,当然他也可以通过从老爹那继承来的赛的方法来塞金额也是可以的啊。 咱们已经验证过了。你看老大是不是可以调这两个封装方法的。嗯,老大对象可以调,那在类模板里头,当然也可以调。类模板之间,方法之间的调用是 ok 的。是可以互相调用的啊。 类模板之间,方法之间是可以互相调用的。明白什么意思吗?明白了。就比如说我在挣钱,这,如果有需要,如果有需要,我在 正前,这,我需要调下边这个方法,那就直接调就行,只不过说不需要对象名了。对,可以直接调的。你看有语法错吗?没有没有。嗯,类模板之间的方法是可以随意调用的啊。是可以直直接直接调的。 语法格式就是方法名加参数列表。这个不受访问修饰符的限制。不受这个不受访问修饰符的限制啊。 好。所以说我在这个里头,我在这个类模板里头,我是可以调我继承来的方法的。因为这个封装方法是我继。这错了,这这个方法是我继承来的,这个方法是我继承来的,就相当于我不写。这也有一个定义,就 相当于这种效果,从老爹那继承来的,就相当于我,这相当于我这就写了这么一个东西,相当于写了这么一个方法啊。所以我在这可以直接调用。 ok? 嗯。所以私有化的成员变量,当对象拥有的时候,可以通过我写在这吧。嗯,对。 此类可以通过此类对象。可以通过 继承来的封装方法来操作此类成员变量。 来操作此类成员变量。此类成员变量是指什么成员变量啊? 是指你从副类那可以拥有的那些成员变量。这不能说继承,别扭死了。此类成员变量是指什么成员变量? 从富力那来的是吧?就不能说继承从富力那来的那些变量。你可以通过继承的封装方法来操作。 那同样子类可以有自己独有的成员变量吗?可以可以不?比如说他想有自己的一个名字 pray with string name, 可以不 可以。那这个成员变量在这方法里头可以操作吗?可以不?当然可以,当然可以啊。嗯,所以我把结论写到这啊。 就和封装方就和那个成员方法是一样的。子类可以有自己独有的成员方法。当然,子类也可以有,也可以有自己独有的成员变量。 也可以有自己独有的成员变量啊。嗯,好。那么咱们把成员变量和封装方法就一块说了,因为他们是有 是有关系的一块说了啊。结论就是结论就是私有化的成员变量不能被此类继承, 但可以被此类拥有。那么此类对象怎么操作这些成员变量呢?怎么操作这些成员变量呢?通过继承来的封装方法。 ok, 通过继承来的封装方法啊。其实说白了就是你隐性的拥有你老爹的财产,你想花,但是得经过你老爹同意,因为你掉的是你老爹的方法,你老爹提供的方法了。 ok, 你就可以花花的爽歪歪。你老爹要不提供那方法呢? 你有那空间是不是也白搭呀?你操作不了。 ok, 听得明白吧应该。嗯,对,老爹如果不提供这老爹如果不提供这方法,你那空间有了又怎么样?你 老爹给你塞进去八百万又怎么样?塞进去八千万又怎么样?你一分也花不了,因为你老爹没提供这方法,他没同意。嗯, ok, 好。那么成员变量和封装方法能不能被继承?咱们就说到这,嗯,就说到这啊。简总而言之呢,就一句话,成员变量不可以被继承,但可以被拥有。 封装方法可以被继承吗?可以被继承吗?可以,因为封装方法一般是帕布里克修饰的。 ok, 好,就到这。

接下来呢给大家讲下一道面试题啊,这个呢是老生常谈的一个面试题啊,我觉得可能十次面试当中最起码要出现七八次啊,就是哈西 map, 这个基本上都会问到,但很多同学呢,有一个容易误解的点就是哈西 map 二次哈西到底是什么? 哈希 map 的 二次哈希到底是什么呢?其实我们的哈希 map 一 共有两次哈希的操作啊,第一次哈希的操作呢是为了干嘛呢?是为了就是说运用我们的一个什么?运用我们的高位扰动算法, 其实也叫散列算法,比如说像那种呃,取我们的一个三十二位的值嘛,取一个三十二位的二进制的值,取他的高十六位。然后呢,比如说跟我们的一个低十六位进行一个易货的这样子的一个运算,所以呢,在原码当中他的一个表现呢,就是这样子啊, 高低十六位进行一个易货呃运算。因为即使是比如说原始的哈希值,他低位相同, 那么这个时候呢,他就有可能我第二次阿奇是去取那个值的一个后四位,后五位。类似于这种,比如说十六个格子数组的大小,或者说十六个数组长度的大小,那我就是取后四位零到十五之间的这整数嘛,那么此时我高位扰动算法就会去减少相同的一个, 减少相同的一个呃,数值带来的冲突带来的冲突,或者说低位相同带来的这样的一个冲突啊。呃,因为我们是高位扰动算法啊, ok, 也就是说我们可以减少相同的这样子的一个所以冲突的概率, 这是他的第一次哈西,而他第二次的哈西呢?呃,他就是什么呢?就他是这样子的啊,呃,他的第二次哈西是做了这样的一件事情,我给大家看一下啊, 比如说我们看到哈希 map, 对 吧?然后呢,它这个铺的方法当中会有第一次哈希,比如说铺的 value, 它就是,呃,在这里呢是第一次的哈希是高低十六位 key 点哈希库德,然后呢去易获上 key 点哈希库德,高低十六位进行这样的一个易获运算,这是第一次的哈希, 而它第二次哈希则是在 put value 方法当中,在这里会有一个什么呢?就是 n 减一与上我们的一个哈希,而 n 减一与上我们的哈希作用是什么呢?各位同学请注意了啊, n 减一与上我们的哈希,就是说首先要结合上 我们的数组的一个长度是二的 n 次密, 然后呢,此时结合上我们数字长度啊,为二的字密了之后,就可以去避免掉我们的一个取模运算, 因为我们的 g d k 一 点七是取模嘛,那么这个时候呢,就可以提升我们的病发的一个性能啊,提升我们病发的一个性能, 那么它到底是怎么去提高我们病发的一个性能的呢?我们可以想象一下啊,在我们 j k 一 点七之前,其实呢,我们首先会有一个就是说,呃,类似于这样子的一个三十二位的二金质的这样子的一个数啊, ok, 也就是说一个哈西扣的值啊,我们会得到一个哈西扣的值,这个哈西扣的值呢,是通过我们 k 值点哈西扣的值了之后,我们都知道啊,我们 哈希 map 它是一个数组加链表加红黑数,我们的链表跟红黑数都是基于我们的数组的,那么这个时候呢,我们数组会有一个初识化的长度,而初识化长度是多少呢?是十六啊,十六的初识化长度,也就是数组的初识化长度 是十六啊。那么这个时候呢,我如果说想要 put 一个数据进入到我们的这样的一个数组,那么这个时候呢,我就希望,比如说得到一个零到十五之间的取值范围 啊,那么正常的情况下呢,我们可能在哈希 map 一 点七之前呢,我跟十六进行一个取模,对吧?就可以得到一个零到十五之间的正整数了,因为除净最大,呃,最除净最小余数为零, 最大余数为十五,对不对?那么这个时候呢,我们就可以得到一个零到十五之间的正整数了,但是他有个问题,就是取模计算,实际上他并不算是一种很快的这样的一个计算。真正快的计算在计算机当中是什么呢?是位运算,逻辑运算 啊,这两个运算才是真正快的,而取模运算其实算下来的话,他并不快,那么这个时候呢,我们就可以想象一下,位运算跟取模运算其实都可以做到,比如说我取后四位数, 而位运算他是怎么做的呢?位运算,其实他是我直接取位操作,取后四位,对吧?最小值为四个零,最大值为四个一,那么就是零到十五之间,对不对? 那么曲位运算是可以做到的,而逻辑运算呢?逻辑运算当中有一个特殊的运算叫做语运算,语运算呢,它也可以做到这样的程度,但是语运运算有一点点特殊啊, 有点特殊,他特殊在哪里呢?他要与上与上一个什么样的值呢?与上一个数组长度减一,数组长度减一的值,而数组长度我们说了初刷长度为十六,那么他减一呢?就是十五,换算成二进制呢?就是这样的一个数字,零四个一, 那为什么说它就能去进行一个曲值呢?因为与运算的特点是什么?与运算的特点是零与上任何数都为零,零与上 任何数都是零,只有一与上一才等于一。 ok, 那 么这个时候问题就来了啊,当我下面为一时,零与一为零,一与一为一,是不是就相当于我把整个数组的后四位给取出来了,对不对?而逻辑预算跟位预算,实际上呢,他们都很快。但是 各位同学,我为什么不用位运算呢?原因是因为我们的数组的长度减一,它固定是这样的一个取值,但当我的数组扩容了之后,比如说,当我数组长度是三十二位了之后,我取一,我取的就是后五位。而我们去进行取值的时候, 为避免最后位数相同,所以我们不仅仅只会固定的取后四位,当数组扩容了之后,我就有可能会取后五位,后六位,后七位,所以此时我们的数组长度就直观重要了。 为什么?因为我们能够直接在哈希 map 的 源码当中去取得这个数,也就是这个 n 我是 可以取到的。但是如果我直接用位计算,我设置一个初数化的值为四,那后面我要不断地对它进行加一,加一,加一,这样子知道吧?我取后五位,我是不是这个数取得后五,它就应该是 这样,取五位,取六位,他就应该取六位,那么这个时候呢?我这个加一的这个操作,他是会稍微的比我们的语韵算要耗性能一些,所以在这里我们用的是语韵算,就是这个原因啊。所以我们 第二次哈希其实是数组长度减去一,然后再与上我们的哈希 啊,再与上我们的哈希,而此时我们的数值长度必须是二的 n 次幂啊。很多同学他可能会说,他说老师,如果说我的数值长度不是二的 n 次幂呢?比如说我给他设定一个说实话的值二十行不行? 各位同学也可以,但是在哈希 map 的 源码当中,这里我们点 this 进去,这里有一个方法叫做 table size four, 我 们点击进去看一下,你会发现它会自动适配成为二的 n 次幂 啊,所以这是我们的第二次哈西所需要进行的这样的一个操作,而我们的一个第一次哈西呢?各位同学啊, 我们的第一次哈西呢?嗯?有没有什么好办法?大家可以想象一下,如果说我们现在有两个 不一样的值,但是虽然说它不一样,但是它的后四位或者说后几位是完全一样的,那么这个时候是不是同样它也会出现,我们计算出来数值是一样的, 而计算出来数值是一样的,就会导致我们可以放进哈西 map 的 同一个这样子的一个桶当中,必然会形成链表或者红 a 数,那么这个时候就会导致链表的长度越来越长,而链表长度越长会导致什么问题呢? 念表有个特点啊,就是我想知道下一个节点的是什么?我必须要知道我上一个节点里面是什么?因为我上一个节点会存储下一个节点的位置, 对不对?而如果我需要新增一个节点,如果用尾差法的话,有可能我就需要把上面所有的念表全部遍历一遍。所以又回到了问题上,我希望我们的一个哈希 map, 它的 index 尽可能的不要重复, 不要重复,那么大家想一想如何不重复呢?嗯, 这个时候我们可以想到,哎,既然说他前面的这样子的一个数值,对吧?不,不一样,那么我把前面的数值也参与运算不就 ok 了吗? 对不对?万一重复了,那么这个时候我才按照列表或者红 a 数的方式进行这样子的一个计算, 对不对啊?是不是?所以这个时候呢,我们用什么算法呢?嗯,我们用什么算法呢?我们就可以用上易货的这样子的一个运算。为什么要用上易货的运算呢?因为易货运算的特点是相同为零, 不同则为一。 ok, 那 么这个时候呢,我们可以让我们的高低十六位,因为一个三十二位的二进之数,我可以让它切分成高低十六位进行一个运算。 ok, 高低十六位进行计算,相同为零,不同为一。也就是说当我确定它为一了之后,我不确定另外一个值的时候,我是无法确定最终的结果的。 比如说像与运算,就是 n 与上一得到的结果一定是 n, 但由于它相同为零,不同为一的特性,所以就算我确定了其中一个数,我是没有办法去确定另外一个数的,所以这就叫扰动运算,也叫充分散列算法啊,充分散列算法, 那么这种算法呢,就可以去避免我们的一个高低十六位的这样子的一个充分计算啊,进行一个高低十六位的充分计算,所以此时就会得到一个逻辑,什么逻辑呢? k 点哈希库德 e 或上 k 点哈希库德高低十六位,进行这样子的一个 e 或运算,知道吧? ok, 所以 此时我们的哈希也整体的完成了啊,所以第一次哈希做了这件事,第二次哈希做了这件事。大家一定要记得顺序啊,我们是先进行的 什么呢?先进行的我们的 e 或运算,再进行的与运算。大家看啊,先在这里就进行了 e 或运算啊, k 点哈希获得 e 或上 k 点哈希获得 向后位移十六位。然后呢与运算在哪里呢? put value 在 这个方地方啊, n 减一与上哈希操作啊 d, 很多同学习惯性地把它给搞反了啊, 怎么搞反了呢?他会认为什么呢?就是我们的第二次操作才是去易货上这样的一个高低十六位。第一次操作是 n 减一? no, 不是 啊,第一次是易货,第二次是雨。 ok, 这是我们的二次哈希的一个操作啊, ok, 那 么讲到这里, nice 加法面试手册二十四把字加法学习路线,从 p 五到 p 八架构师加法面试场景题私信我或评论区留言。