00:00
那么例呢,我们就说完了啊,那接着的话呢,我们再讲一下collection的另外一个子接口,那就是这个set接口了,打开它。那么关于这个set的话呢,诶首先呢,这块提到说它及实现类这个特点,我们呢,先把这个里边的关于set这个,哎架构呢先拿过来啊,咱们就先粘到这儿啊,关于这个绿色这块呢,咱们就删掉了。哎,来讲一下这个set的问题,Set的话呢,它首先是我们这个collection的一个接口了,用于存储叫无序的不可重复的数据。啊,类似于咱们高中讲的这个集合的一个结构了。诶,是这样一个特点了啊好,那么这个side我们怎么讲呢,也是遵循咱们下边提到的这样的一个层次,咱们这一章呢,主要是讲这个层次一和这个层次二啊第14章的时候呢,我们在讲这个层次三。这个层次一里边呢,就涉及到了我们主要用的这个实现类是谁。啊,会造对象,然后会调方法。哎,就这个问题好,先说它的话呢,回过来这块呢,我们就说清楚了,这个set接口它的主要实现类啊,就是哈西塞。
01:06
就他是吧,呃,另外的这两个呢,咱们也先给他这个整下来是吧。先这么着一下啊。嗯,好,它呢就是主要实验类了。那就意味着从这个层次一的这个角度讲呢,我们只需要呢,会造这个哈希set,造一个他的对象就行。那下一个呢,就涉及到方法了,方法这块呢,说set中的方法都有哪些呢?这块我们打开这个API,这块你写上这个set。U下的ex set1进来,然后呢,我们主要关心的是它的这个抽象的方法,然后呢往下一看。好像似曾相识。发现呢,跟咱们collection当中定义的这些方法你看都是一样的是吧。呃,言外之意呢,就是我们这个set当中啊,相较于我们这个collection来讲呢,它没有额外的再去定义一些方法了,那我们使用的方法呢,都是collection当中声明过的。啊,我们在这儿稍微说一下啊set中的常用方法说即为啊collection当中。
02:07
哎,声明的啊,这是15个抽象方法。啊,没有新增的方法。其实他这块呢,咱说白了啊莱呢,为啥就那15个方法呢,主要也是为了迎合他。因为人家这个例子呢,因为有索引,所以人家呢多了一些方法。但是呢,我呢,又作为绿色和赛特的通用的这个副接口了。主要是为了迎合它,所以呢,我们只能是定义这么15个了,人家的人多是因为人家有索引是吧。OK啊行,那么再拉回来,那这块呢,其实已经说的算是比较清楚了,所以从第一个层次来讲。啊,这块呢,大家能做的事儿,或者说呢,需要掌握的事儿比较简单啊,你只需要呢,会这个操作就行了。比如我们这呢,来一个哎set的一个测试啊过来,哎首先呢,来一个单元测试啊,哎我们呢,哎你声明呢,可以写成个set,后边呢,我们就new一个呢叫哈希set了。
03:03
这就我们所谓的叫主要的实现类,你会造对象非常简单,空参构造器啊,然后呢方法呢,就我们前面讲的collection里边呢,十几个方法了。比如说通过它呢,我们去艾特一个啊叫A是吧。啊,再去艾特一个,来个123。挨了一个挨一个。哎,比如说BB。啊set点艾一个,这在咱们没有这个person了,把这个person呢,我再CTRLC一下,粘到咱们当前这个下边啊CTRLV。哎,过来啊。好,回来这块我们再去new一个,哎,Person Tom。诶,12岁,哎,这就可以了,好这样的话呢,我们就添加了这样的四个元素。哎,添加四个元素的话呢,那我们可以呢,比如说建立一下。便利的话呢,还可以使用迭代器。啊,得到一个他的实力well。I turned their heads next。打印一下,点next操作。
04:00
哎,这就可以了,好走一下。哎,这就成了。嗯,出来了啊,诶这时候我们也发现呢,咱们添加的一个顺序呢,你看跟我们便利的顺序呢,不太一样是吧。咱们说诶无序性。啊,这个无序性到底指的什么意思呢?咱们一会儿再说,至少呢,我们现在看到呢,不像俄一样,哎,就是按照你添加的这个顺序呢,去进行了便利,这呢似乎呢不太一致了,这也是正常的啊。好,那其他的方法呢,我就暂且呢不多去测试了,所以呢,从这个层次一的角度来讲呢,大家呢,针对于set的使用就知道呢,我们去new哈西set这叫主要实现类了,要方法就是collection当中当初我们提到的这样的一波方法。因为呢,这虽然是接口,但是方法的作用参数什么意思都是确定的啊,OK,那当然啊,自然而然的啊,我们现在往set里边去放进一个person的对象了,这个person呢,是不是仍然得需要呢?重写equals。没问题,因为这块你还是有可能是不是通过这个set点,我们调这个contents是吧,判断一下你是否有这个person,是不是还得去调那个ES吧。
05:04
啊,比如这块我们来一个打印。啊,这个我们来一个。哎,这不是还得诶。False是吧,啊这块呢,一说呢,其实就有点儿多了。嗯,抛出一个新的知识点是吧,你发现呢,这个事儿呢是不靠谱。对吧。哎,不靠谱,那什么原因造成的呢?诶我们先找到这儿哈,这个呢,我们就不得不去引入这个叫哈希Co了。我把它给打开了是吧,打开以后呢,回过来我们再去走哈。你看是不是就变成出了。很神奇是吧?啊这个事儿呢,咱们等一下专门来说这个啊,啊至少的话呢,我们说呢,在这个里边呢,咱们需要呢,去重启一下这个ECO的方法啊,那么哈库的这个事儿怎么看待呢?稍等一下,咱们说哎,咱先把其他这个内容先补一下啊。所以从这个层次一的角度啊,先清楚我们说的这个问题,好,然后呢,再拉回来啊,这个set呢,我们宏观上来看一看啊,Set的话呢,我们就要存储无序的不可重复的数据。
06:08
哎,那么它的使用频率是什么样的呢?啊,因为咱们在一开始讲这个集合的时候呢,不是看了两个这个生产当中的这个图嘛。对,咱们说呢,整体来看的话呢,这其实相当于是一个例子了。然后呢,具体这一个位置呢,我们可以封装成个对象,也可以呢,用一个map去装啊,每个位置呢,一个KY61个KY6K6,你会发现呢,这个场景当中没有set的这种使用场景。而实际在开发当中,我们赛赛啊用的确实是要少一些啊。所以这块我们写的话呢,就是哎,相较于咱们说的list,或者是这个map来说。啊,这个set呢,使用的频率。比较少啊。比较少。行,这呢是我们相当于一个使用频率的一个问题啊,那下边呢,涉及到它的一个使用场景,也就是说呢,什么时候我们会用这个set呢。
07:06
啊,如果我们主动去使用的话呢,通常呢,都是用这个set呢,是用来过滤重复数据的。啊,因为它这里边儿的数据不能重复嘛。哎,那假设呢,我们现在有一个容器啊,或者要一个集合了,里边有一些数据可能会有重复,那我们这呢,只需要把它添加到我们这个set里边,所谓的重复的数据呢,自动的就给过滤掉了。这就是他的一个主要特征啊。这个呢是用来啊过滤啊重复数据的。这个指的是咱们主动使用的话啊,呃,那被动使用什么呢?就比如说我们会调用一些系统的API,这个API的时候呢,你可能调某个方法,这个方法的返回值呢,是个set。啊,其实呢,他就想表达呢,就是它里边这个数据呢,是没有顺序的,也是不能重复的啊,那他是个防位之赛的,那就拿菜接收就完了。这就算是叫被动使用啊,主动使用呢,就是来过滤重复数据,好这个事儿呢,我们就说清楚了。这个说完以后的话呢,我们接着来看一下这个层次二,那就是区分一下接口当中不同的实现类的一个区别,在这儿呢,我们主要呢,就讲这样的三个实现类。
08:10
啊,那么这三个实验类呢,他们之间是有什么样的特征呢?首先呢,提到了哈西set是一个主要的实现类。那么下边这个呢,叫link的哈set啊,你看呢,它其实也是一个哈set。是在它的基础上呢。加了一个link是吧。哎,这块呢,其实我们把它呢得往后缩一下了,它呢其实是我们的哈希set的子类啊。哈伊赛的一个子类。这里有这样的一个特征啊好,那么这个hi塞呢,是我们说的一个主要的实现类了。啊,那么另一个行业赛呢,在他的基础上又干了点什么呢?加了一个link是吧。是不是加了一对指针,或者我们叫链表?啊,那本身它是什么样的结构呢?其实这块一说的话呢,就涉及到它的底层的一个存储结构了。
09:02
咱们就这样泛泛一说哈,首先呢,这个哈希赛的它的底层呢,使用的是咱们先说呢,就是哎哈希map。啊,这一说呢,就涉及到我们后边那种是吧,哎,那咱们就过掉哈利map,那就涉及到哈希map底层使用什么呢。啊,即使用叫数组加链表,这个链表呢,是一个单向链表。然后呢,又加了一个叫红黑树。诶,红黑树啊结构进行存储。啊,这个大家呢,你先这样一听,因为咱们到下下章才专门的讲这个数据结构的问题了啊,你看了以后呢,别紧张啊。它底层呢,是使用这样的一个结构存储的,这块呢,咱们还要注明一下是在JDK8当中啊。什么意思啊,在JDK8之前没有红。啊,只有数组加单向链表啊,GB8的时候呢,我们才引入了一个红黑数的一个结构了,啊,就像这呢,就我们说的叫哈希map。
10:06
而这个link的哈西是吧,它呢是既那其实呢,相当于它底层的话,也是类似的是这个结构啊,它在这个结构基础上呢,又加了一个link,相当于呢,我们在现有的这个结构的基础上。啊,我们说啊,在现有的哎,我们叫数组加单项列表加红黑数结构的基础上。啊,又添加了。哎,添加了怎么着呢叫哎。我写到这儿啊,又添加了啊一组双向链表。挺住啊,这个咱们先写完之后我给你解释。诶,又添加了一组双向链表啊,用于。啊,记录添加元素的先后顺序。
11:00
啊急什么意思啊,我们呢,可以按照。哎,添加元素的顺序。实现便利。哎,就是这样的效果。啊,这呢,就我们这个另一场哈西赛的一个效果,诶你看这玩意说写了这样一句话啊,我们可以按照添加元素的顺序实现便利回过来。诶原封不动的,我把这个代码呢,CTRLC一下,我呢在。复制一份这个我们叫叫T2,然后呢,我把这个哈希set呢,改成叫link的哈希set。其他位置呢,不变,这个我就删掉了啊。哎,这个呢,我就在这儿也主持一下吧。好,然后呢,我们现在呢,添加了几个元素。啊,刚才呢,咱们在演示便利的这个时候呢,你发现呢,便利的这个元素的这个顺序啊,跟咱们这块添加的顺序呢,不太一样,可能有同学就会认为说,哎,这就是无序性。好,如果你要认为这就叫无序性的话呢,那我们下边这个呢,你可能就迷茫了。
12:01
你会发现呢,我们用这个link side呢,我们遍历的顺序和你添加的顺序呢是一样的,你随便呢去调。啊,我们再来。哎,你看是不是仍然如此。啊,然后这个呢,其实就是。怎么做到的呢?就我添加了第一个元素之后,哎,它第一个元素呢,就有个指针呢,就指向第二个了,第二个呢也有个指针,就指向第一个了,哎第三个呢,指向第二个,指向第三个,第三个指向第二个,这就是这一对双向指针。哎,我们就这样链接一下,那你可能会问说为什么要这样做呢。对。我们既然可以呢,按照氢加元素的顺序,时间便利了,是不是便于?诶,我们频繁的这个查询操作。注意是频繁的,如果你就查一次呢,其实也没必要非得用它了,你用哈希赛的也行是吧,你要频繁的去查询的话呢,那就意味着我只要找到第一个元素,你是不是顺着这个指针,是不是就就能找到第二个了,是吧,第二呢就能找到第三个,第三个找到第四个,所以呢,我们遍历的时候呢,比较方便一些。
13:07
哎,就是这个原因啊。好,这是我们说的他们哥俩。这块你不用太担心,因为面试的时候不会问他们的区别啊。面试要问的都问哈希map。其实呢,也等于就问了他。因为他要问你他的时候你就说哈尼ma就行是吧。啊OK啊行,然后下边这个呢,叫ET,这个ET的话呢,它跟咱们这个哈,ET它是并列关系啊。你看他的前缀。叫tree。对,Tree呢,就是树的意思是吧,哎,那就意味着它底层使用的这个结构呢,跟他们都不一样啊。哎,那么它呢,底层使用叫红黑树啊存储。哎,当然了,公因数呢,就属于阿叉树的一种是吧?OK啊行,底层在使用红黑素呢来进行存储,那它的特点是什么呢?啊,这呢,我们说呢,可以按照指定啊,因为咱们添加的都是一个一个元素了啊,可以按照添加的啊元素的指定的属性。
14:09
进行便利。啊进行遍历,就是我们添加呃好多这个元素了,然后呢,我们添完以后呢,我们再去遍历的时候呢,你发现呢,它按照你指定的某个属性的大小顺序呢,进行遍历了。指定的属性的大小吧。顺序啊进行便利,好这呢就是这个ET。啊,当然大家可能感兴趣说,诶他到底怎么做的是吧,这个咱们往后一点去说。呃,先在整体上先把他们的一个特点呢先说清楚。那么这个层次一和层次二呢,咱们就说到这儿了,说到这以后的话呢,其实咱们要给大家呢解释一个问题,这个问题呢,就是我们刚才提到说set里边存储的叫无序的不可重复的数据,哎,包括呢,刚才我在测试的时候呢,我这儿呢,不是有一个这样一句话吗。这句话写完以后的话呢,我们再进行content判断的时候呢,如果针对于person呢,咱们仅是啊里边呢,重写了它的E的方法,你发现呢,没有在重写哈希扣的这个方法的情况下呢,在判断的时候呢。
15:07
并没有认为我们当前包含这个person是吧?哎,那么我们下边呢,就要解释一下这个问题。这个问题呢,其实就涉及到了这个元素,它到底是怎么添加到这个set里边的。啊,这个解释的话呢,咱们就通过这个来入手就行,怎么着啊,就是这个set呢,它存储的元素叫无序的,不可重复的,我们怎么去理解这个无序性和不可重复性的问题,哎,这个说清楚了,我们刚才这些疑问呢,就全部都搞定了啊。好,那我们就分成这样两个角度来说,第一个呢叫无序性,第二呢叫不可。哎,重复性啊。OK好,那首先呢,针对于这个无序性呢,咱们先说两句啊,这个无序性呢,首先回到我们这个测试这个层面,先看一下我们这个哈希set啊,我呢刚才运行的时候呢,出来了一个结果,这个结果呢,跟咱们添加的这个顺序啊不太一样。
16:02
那我就放这啊,暂且呢,咱们把这个呢,就先注释了。好,你看不一样哈,那我要再去运行一次,你首先看一下我们每次打印出来的跟第一次打出来这个顺序是不是一样的。对,你每次运行发现都一样。所以呢,我们首先啊,此时的这个无序性啊,它首先呢,叫不等于随机性啊。不是说呢,我们这个无序了,说每次打印出来这个先谁后谁都无所谓了,呃,即使是无所谓,当然也不是说你这块打的时候呢,就今天这样,明天这样是吧,这个不是随机的这个注意每次呢,它都有一个固定的一个顺序了。啊,这是我们说的第一个问题啊,那么一个点先说清楚,然后第二事啊,这个无序性呢,是不是说可以理解为啊,就是我们添加的时候。啊是这样子的,然后呢,便利的时候呢,跟我们添加的这个顺序呢不一样。这是不是就叫做无序性呢?
17:02
再说一遍啊,我们添加的顺序和便利的顺序呢不一样。这儿是不是可以理解成叫无序性呢?因为呢,我们前面你看讲release的时候,包括这个像例子里的时候呢,啊,你添加的顺序跟我们遍历的顺序是一样的,咱们说叫有趣的是吧。啊,那现在呢,我们添加的顺序跟变量顺序不一样,所以叫无序性,似乎呢也没啥问题,但是。还有一个link的哈赛。这个令的含义在哪?你看我们运行。你发现呢,添加的顺序跟你便利的顺序呢,是一样的了。那你说这个事儿你咋解释啊,你说link含set它是有序的,那你还实现set接口了,Set叫无序的,那你怎么成有序的了呢?对吧?哎,所以说呢,我们在这呢,可以说一下啊,诶一方面啊,无序性呢,它不等同于随机性,另外一方面呢,这个无序性呢,它也不是指咱们添加的顺序呢,和便利的顺序呢,不一致的啊说这个叫无序性也不对是吧。
18:03
哎,在这写啊说呢添加。啊,元素的这个顺序啊和电力。啊,元素的这个顺序。不一致。啊,是不是就是无序性呢。哎,这个呢,我们要说一个no是吧。不是的。啊,就是说他也不是表示为无序性,那么下个问题说到底什么叫无序性。无去行是吧。嗯。这时候的这个所谓的无序性啊,其实呢,我们想说的呢,就是跟添加的元素的位置是有关的。啊位置啊有关,那就意味着呢,它不像咱们的a release一样,A release当中咱们是一个数组是吧,它是第一个放这儿,第二个放这儿,第三个放这儿,它是依次紧密排列的是吧?这个呢,就体现为是一个有序性,只不过我们便利的时候,就按照你添加的这个顺添加的这个依次放的这个顺序来的。
19:12
哎,它这种啊叫一个一个挨着量放的,它叫有序的哈,咱们这里边呢,说跟添加的元素的位置有关,盐外G呢,它就不是依次紧密排列的。啊说不像咱们的啊a release一样。啊,是依次紧密。啊,排列的。啊,那么下一个问题就是它到底怎么排的呢?这我们就比较感兴趣了是吧,好,这个要怎么排的话呢,咱们其实就引出了一个问题啊,大家一看现在的话呢,我们有个容器啊,这个容器呢,它存放的元素呢,是不可重复的。啊,这个微信呢,你先不要管啊,这个它存放元素呢,是不可重复的,假设呢,现在把这个需求呢,抛给你了,让你设计一个容器,里边的元素不能重复。啊,你怎么做。
20:02
不能重复是吧?言YG呢,你比如说我们这呢,你看我CTRLD一下,是不是又来又来了个AA是吧,那就后边的AA呢,是不是就进不去了。哎,所以这块你看我们这里边儿就只有一个A。啊,你不管拿它测也好,拿这个,呃,哈利塞的测也好,都是这样的啊啊,你怎么设计呢。啊对,这个大家这个思路呢,其实也比较清晰,其实呢,也相对来说容易想到是吧,就是说我们添加第一个元素的时候呢,那你就进来了。啊,添加第二元素的时候呢,为了保证这个不可重复性,我们得跟第一个是不是比一下。比一下,如果一样了就不要添加了,不一样进来。那这不挺顺的是吧?啊,添加第三个,第三的话,你得跟第一个和第二个都得比一下是吧?哎,都不一样了啊,第三个进来,以此类推。感觉上呢,也没什么毛病。但是你会发现呢,随着这个N的增加,我们这个复杂度呢,急剧的增加。
21:00
对,比如我现在已经添加了1000个元素了。我在添加剂1001个的时候哈。这个事儿呢,很很悲壮是吧。然后跟一个一个元素去比。走走走走,结果跟最后一个比的时候发现一样的是吧,还进不来了啊,诶每一个元素都对比一遍,随着这个元素的增加呢,这个复杂度呢,急剧的增长。所以说呢,这不是一个好的选择。啊,那么这个赛的话呢,它主要呢,诶我们说呢,就来过滤一下这个重复的数据,它就不能这样来做,这样做呢,性能太差了。怎么来做呢?哎,他这块用到了一个叫做诶哈希算法啊。哎,一说到这还上面就感觉就诶高大上了是吧。哎,这个怎么来设计呢。哎,他这样来设计哈。哎,还是一个数组。啊,还是用这个数组第一个元素呢,其实无所谓了啊,怎么着都行是吧。哎,当然呢,这块我们从一开始的时候呢,设计的话呢,就要考虑到,哎这个这个第一个元素啊,虽然说呢,没有之前的元素跟它是一样的了,但是第一个放的时候呢,我们也要遵循相关的这个算法了,怎么做呢?哎,我现在有一个元素了。
22:11
这个元素的话呢,呃,我呢,就放的时候呢,不乱放。啊,它呢,就放某个位置,这个位置的话呢,根据这个元素啊,它有一个方法叫哈西扣的方法。我就先算它的一个叫哈希值这样一个数。比如说这个哈希指认没什么概念,你又可以当成呢,针对这个对象的一个标识。对,或者叫个编号也行。是吧?就是一个编号啊,那这个编号的话呢,是通过一个哈希库的方法算出来的一个编号啊,而这个编号的话呢,就决定了你在这个数组当中存放在哪个位置。就好比大家军训一样,是吧,军训的话呢,这不是有一排这个营房嘛,说告诉你是啊,哪个哪个号啊,你就顺着这个号去找你住哪就行了。啊,类似这样的一个道理啊。好,假设我们这个对象的这个标号呢,叫1234。
23:03
啊,就是1234,注意咱们这个数组呢,可能没有这么多个元素。啊,假设这个数组的长度呢,只有16是吧,那这个角标呢,就是从零到15了。哎,脚边呢,只有这些,那你这个1234,你你到底坐哪呢。咱们可以简单想一想是吧,哎,先设计一种方式吧,比如说啊,你这个数呢,我们让他取模。16。啊,一个数曲模16,结果呢,是不是只能是零到15范围内的,哎,这不就有一个办法了是吧?哎,那么底层呢,它其实用的不是这个曲膜,它比这个曲模呢,性能还要更好一点啊,咱们先这样去理解。取个16,哎,我们这块呢,就一算,假设能得到个数,这个数呢,一定是在这个范围内的A,我就做到这儿了。第一个元素呢,因为之前也不存在别的元素,那你就做到这儿。没问题是吧?好,那么接着我们又添加一个元素,这个元素呢,同样呢,是不是也得调一下哈希库的方法,也算出一个哈希值啊。
24:00
那么这个含义值的话呢,算完以后,诶,然后呢,还是曲模16,诶它做到这个位置,这个位置上也没有元素,它就也做到这儿了,也就说诶你跟第一个怎么不比呢。这时候对这块我有个要求,我的要求就是什么呢?你俩要是真的死的话呀。你们算那个哈希值呢?也得一样。这就咱们所说的叫哈西扣的方法和E扣的方法呀,得一致。我再说一遍啊,就是这俩呢,如果你要用equal的方法去比出真一样的话哈,比如说你这个呢叫汤姆12岁,这个呢也叫to姆12岁,显然equals是true的是吧,那我们在计算哈值的时候呢,也让你俩的哈值呢也一样哈。你要孩纸也一样,你俩肯定就坐一起了嘛,是吧?哎,然后就得下一步再比较了,那现在呢,你俩呢,只要不是E斯呢,咱们让你们算的哈希值呢,看也不一样了。那就避开一下这个问题是吧。OK,行,第二元素添加好,诶第二元素假设就在这儿了哈,现在第三个元素,比如说咱们现在填的还真就是TOM12岁,第一个呢,就是汤姆12岁,第三个还是。
25:06
那这样一算呢,它俩的含义值是不是就一样了?它也是一样,你在取模16是不是也对应的也得在这个位置啊。这是第一个,这是第二个,第三个的话呢,我们添加是不是就得。在这儿了是吧,在这儿的话呢,我们也要放在这儿了,那怎么办呢。咱俩E一下。实际上呢,E口子之前呢,可以先比一下哈希值的。你动,这还用比吗?就是呃,这儿呢,咱们都是汤姆12岁的,他也还是一样的,但是也有可能你算的另外一个哈伊值跟这个哈伊值不一样,但是呢,一曲模16的时候呢,余数一样是吧。哎,这个也有可能。是吧,诶所以呢,一般呢,就是过来以后呢,先比一下咱俩的哈希值。哎,还有人呢,如果要是不一样了。还是认为咱俩就不一样了,这就进来了啊,诶如果哈一这要一样了。咱俩在e cos一下,E cos一看呢,发现咱俩还真一样是吧,那这个呢,就不要进去了。
26:07
啊,就这样个道理。啊,那再来一个元素,同样的道理先呢,拿一个哈希值先算个数。哎,哈库的方法算一个哈值,然后呢,诶,比如说取默认16,看你要做在哪,如果呢,这个位置上没有值。就直接坐这儿,如果要是有值的话呢。看看咱们俩的哈希扣的值一样不?不一样。就认为咱俩不一样了,一样了。咱俩在ES一下是吧。哎,这样的一个思路,看看能不能理解。诶,咱们这里边儿有个要求,就是哈西扣的这个方法和E扣的方法呢,他俩得一致。啊,它俩得一致,什么叫一致呢?啊,如果echo的方法呢,是出是吧。那咱们就让你俩的这个哈希值呢。
27:00
是不是也一样,是吧?啊这样啊,诶还一直呢,如果要不一样呢。诶,这时候E让他们也不一样是吧,你可以这样的去理解这个一致性。其实这样的话呢,我们就避开了,你每次比如我们这个元素添加已经很多了啊,假设呢,已经有1000个元素了,当然了这个1000个元素的时候,这个数组的长度肯定不是16了,也很长啊,然后呢,我们现在又来一个元素,这个元素呢,我们看看到底要放在哪儿呢,它不需要呢,跟之前的1000个去比。它只需要呢,看你要放在哪是吧,你放在这个位置呢,看看有没有元素,如果要是没有元素呢,就直接就放这儿了,有元素的话呢,刚才我们说到了啊,诶假设我们这个一,咱没有说这个问题啊,假设有另外一个元素要放在这个一的位置呢,呃,它俩哈希值呢不一样,它就也放了,其实呢,这个时候呢,他们就是一个链表的方式呢。去链接的哈。啊,就都放在这儿,他们彼此之间是不一样的啊,那现在我们这个元素呢,过来之后呢,如果这个位置没有元素就放了,如果要是有元素呢,元素的话呢,我们就跟这个元素一个一个比一下,看看大家是不是都一样,如果都不一样了,这个你也可以再添加进来是吧。
28:09
哎,就这样的思路,这样的话呢,我们就大大的减少了跟现有的元素的一个比较了。啊,这呢就叫做哎哈希的这种算法,然后把这个表,这不是一个数组嘛,哎就称为呢叫哈希表。啊,就是这样一个思路啊。行,诶,肯定很多同学呢,还是比较懵的,没关系,咱们后边还讲map呢,咱们后边还讲第14章呢,是吧?这个事儿呢,我们都会去展开来说,现在呢,你只是泛泛的先去理解一下啊,哎,那么还回过来说说什么叫无序性呢?哎,无序性呢,就是我们刚才说的这个事儿,你只能是个数组,如果呢,是第一个元素在这儿,第二个在这,第三个在这儿,这肯定叫有序的,怎么叫无序呢?是我们第一个元素啊,移过来,根据哈值呢,再取个模,第一个在这儿。第二个在这了啊,第三个跑这了,哎,第四个又跑这了啊,第五个呢,又成这样了。哎,整体来看的话呢,你们是无序的。
29:01
啊,那么link的哈希赛呢?对,它也是无序的,因为它也这样放是吧,只不过呢,它在这样放之余。它呢又多了一个指针,你第一个呢指向一下第二个,第二个呢指向下第一个啊,第二个呢指向下第三个,第三个呢再指向下第二个啊,第三个呢在指接第四个啊,四个呢指接诶第三个,这样的话呢,你在便利的时候,它不就找到一。是不是顺着这个顺序就找到后边元素了是吧?那你要用哈希塞去编利的话呢,它就会这样啊,二有一个四有一个中间这块都走一下,没有一找了,哎,又找一个五啊,这块又走一遍,又没有找个三,它不是就慢吗?是吧,哎,就这样个特点啊,那为什么每次便利的时候,哈伊赛呢,都是同样一个顺序呢,他每次都是24153。24153。是吧?对,存储位置没变,它变了的话呢,它就从头开始找呗,嗯,就就这样,所以呢,咱们说的不是随机性,每次顺序一样,它不都是24153吗。
30:01
那就这样啊,好这块呢就回来啊说呢,诶什么叫无性呢,它跟存储的位置有关系,那存储的位置有关系,不像哈伊塞一样,是依似紧密排列的,说这里呢,是根据呃添加的。哎,添加的这个元素啊的哈希值是吧,计算的其在数组中的这个存储位置,然后此位置呢。啊,这个不是这个叫什么,依次排列的是吧。啊,不是依次排列的。然后呢,表现为啊,这叫哎无序性了。诶,所以呢,我们真正无序性呢,指的是你放的位置呢,一个在这儿,一个在那儿,一个在这儿,一个在那儿啊叫无序的了,好这个说完以后的话呢,自然而然的,我们这个不可重复性呢,其实也就能够表达了。哎,首先呢,不可重复新呢,指的就是我们S中添加元素呢,是不能重复的,那这里边就提到不可能重复的标准是什么是吧。啊,这里边儿怎么去说呀。
31:03
对,首先呢,我们描述描述一下啊,就是添加到这个set。哎,中的这个元素呢,是不能相同的是吧。呃,其实呢,我们这个不能相同,本质上来讲呢,其实还是看ES。只不过呢,在这个E和之前呢,我们又加了一个哈希扣的一个数的判断是吧,这样就能避免它跟现有的这个数去比了。啊,就这样情况啊,哎,这个元素是不能相同的,然后呢,哎,这个比较的标准是吧。啊,需要呢判断。啊,这个哈希扣的。在我们去进行E扣之前呢,咱们先有一个哈希扣的一个判断啊。哎,需要呢,判断哈希扣的,哎得到的这个,通过这个方法啊,得到这个哈希值。这个哈希值呢,其实就我们这个。它的一个音译是吧,通过判需要判断哈扣的这个方法呢,得到的这个哈值与啊equals方法。
32:04
哎,得到的这个结果,哎是否是相同的是吧。哎,这个你看这样说吧。诶,比较的标准需要判断,这个我们写到这儿吧。诶,需要判断哈库的得到利哈伊值啊以及是吧。啊,依护的方法得到的这个或者型的结果。哎,现在这个结果。啊,结果啊,哎,怎么着呢,算式叫相同的呢。诶,这里边儿其实就提到了我们说这个一致性的问题是吧,就是这个,诶high的这个方法呢,跟这个equal方法呢,我们要保证这个一致性啊,这个如果是equals的话呢,哎,如果是个处,那我们得到这个哈,Co的这个值也是一样的。啊,那这个怎么算这个不相同呢,那就意味着啊,嗯,这个哈希值。啊哈,一直相同是吧,且。
33:00
哎,这个E的方法。对返回处诶则认为。呃,元素呢,是相同的。哎,注意哈,那如果哈一直要是就不相同。那肯定就不用再去判断后边这个事儿了,是吧?哎,就这样啊,行,这个呢,就是我们说的这个不可重复性的事儿了,好那么整个看到这个事儿以后呢,对我们的一个启示是什么?这个就是我们解释刚才说的这个事儿了。啊,为什么我们在这个啊,这个里边呢,咱们只写了一个。诶equal方法,然后呢,没有去写这个high方法的时候呢,他竟然判断我们这里边呢,是没有这个person的。言外之意啊,就是你看上面这块呢,我要是在CTRLD一下,这是不是又添加了一个。那就意味着啊,我就不拿它去判断了啊,意味着这时候呢,是不是两个都进去了。说明明这俩一样,怎么都进去了呢。
34:00
按照我们刚才说的这个标准来哈,怎么算相同呢?就是含一值相同,并且这个呢,返回值还是处,这就是相同的。那现在咱们知道了,这个反馈肯定是出了。只能往前推,这个哈义值不一样是吧?呃,这个原因就是在于,如果咱们没有去重写这里边儿的含义库的方法的话呢,你可以理解成,诶,咱们调的就是object里边的哈义库的方法了。这个哈方法呢,你可以理解成就是随机给我们算了个数。啊,这个我们不是理解成就相当于我们对象的一个地址嘛,相当于你在对空间里边就给你找了一个空间啊空的位置呢,给你诶放一下是吧,所以呢,我们诶这个对象和这个对象呢,它的如果没有重写high方法,它的哈值不一样。还值不一样了,是不是根本都没有给你机会去调E口方法?所以你会发现呢,我们这块呢,虽然加了这样一个输出语句,而在我们刚才的这个执行过程当中,根本都没有调这个ECO的方法。哎,就是这样一个原因是吧,好,那我们要想这个元素进不来怎么办呢。对,你只需要呢,把这个方法呢做个重写就可以了,这个重写的标准呢,其实也很清晰啊,就是呢,让我们当前这个类的属性呢,都参与运算相同的属性值,得到的含义值就是一样的。
35:12
啊,你要愿意点开看,你就点开看一下。点到这就好像不想点开了是吧。哼。看着有点多了是吧,其实呢,就把这里边儿的我们不就是一个name一个是age吗。呃,其实就是呃,先调他们各自的元素这个含义值,然后呢,做一个累加的一个计算了,实际上这呢是一个细节的算法啊,这个大家可以先不用过多的去研究,后边呢,我们讲源码的时候呢,再看也来得及啊,好,当我们把这个方法给重写以后哈,回过来我们再去添加的时候。这个呢,我说呀,就进不去了。啊,你看我们先看结果。你看就一个了是吧,而且呢,这个一的方法呢,你发现也掉了。这就是因为呢,我们前边呢,那已经是放了123这四个元素了啊,不管他们放哪吧,反正是放了啊,然后当你再放的时候呢,我们计算一个哈值,跟上面这个哈值呢就一样了。
36:07
还是一样的话呢,我们再取摸一下,呃,比如说是16个元素吧,取摸一下16发现呢,你跟你第一开始的那个person对象是不是要放同一个位置啊。这时候咱俩先哈个纸比一下。咱俩是一样是吧,啊,咱俩值一样了,然后。咱俩得ES一下是吧,哎,E的时候一比发现还真一样,所以呢,我们就看那ES呢调用了。哎,这样。诶有没有同学会觉得说,诶这个我们去比这个哈希值的时候呢,已经一样了,那不就意味着说你这个就相同了,就别进去了呗。不是这意思,就是我们现在啊,比如说这个呢,我们假设啊,嗯,我这样说吧,假设它是15。那就抛开这道题吧,就是如果有的这个数呢,算的还一直是15,然后另外呢,算的是叫31。这两个呢,如果去取模16的话呢,其实都是15是吧。哎,这时候我们去比一下哈,值它俩还值不一样。
37:01
诶,我说的还不是这个意思啊,我说的是你算完以后呢,假设这个是15,另外一个还是15。那这时候呢,还一值一样了,那为什么还要再去比一下ES?是吧,就是虽然咱们讲要保证一致性,一致性,但是还是怕有点这个风险。啊,什么风险,举个例子哈,呃,比如说呢,咱们有一个人的名字呢,他叫A,他的年龄是12岁,呃,另外一个人的名字叫B。是吧,他是这个11岁。假设呢,你这个哈,方法呢,写的非常简单,就是他俩的加法是吧。是不是还是有可能性,这个呢,咱们假如叫97的话呢,算个数,它是98,这个还小一个,他俩这个数是一样的是吧。就还是有点这个风险哈。所以说的话呢,诶你要是你俩哈一直要一样的话呢,咱俩还是稍微的还得e cos一下是吧。哎,就是这个意思啊,就是保证我们确实呢,重复的就不能进去啊。好,这个我们再拉回来,哎,这个呢说清楚了,好这块呢,结论啊,添加到哈希set或者叫link的哈希set当中,对元素的一个要求。
38:05
哎,我们说呢,光重写E口子就不行是吧。要求呢,就是元素所在的类要重写。两个方法是吧。对,一个呢,是咱们之前重写的异构方法和。对这个哎,哈希扣的这个方法,然后呢,同时啊。哎,我们说呢,要要求两个方法呢,要保持一致性是吧。哎,就是尽量的,我们说这个如果是出的话呢,你也一样。是吧,就是我们刚才说的那个场景啊,哎,那咱们在写的时候可能会担心,哎呀,我要是写不一致怎么办呢,这个呢,你就别自己发挥了,我们是不是就自动生成啊。哎,说呢,诶我们,诶只需要。啊,这个在idea中啊。哎,自动生成。哎,自动生成,诶两个方法的这个重写即可啊,也就是说技能。
39:08
哎能,哎,保证这个两个方法的一致性啊。啊,因为呢,它在这个自动帮我们重启这个high方法的时候呢,它其实里边呢,也做了相关的这种算法的一个设定了。你像这时候用这个31啊,其实呢,就是算不大不小的一个数数是吧,哎,它这种迭代式的这种啊,相乘其实就尽可能的让我们规避掉啊呃,如果两个对象要是一样的话呢哈,值这块呢。也就是两个对象如不一样的时候呢,这个亥值呢,尽量也不一样是吧,哎,这样一个情况啊。好,这呢是咱们对应的这样的一个结论,那这块呢,大家多少还有一些迷糊的,没关系哈,先不用纠结到这儿,诶咱们呢,后边还讲map呢,咱们还讲这个源码呢,是吧,到时候呢,我们这个事儿呢,要展开的给大家再去说一说,现在呢,先有一个这样的一个了解啊就可以了。
我来说两句