00:00
前天呢,我们讲到这个set接口了,Set接口这块呢,首先来说一下,整个来说set特点大家需要去注意一下是吧,这个呢是比较简单的哈,另外一个点的话,那个site的话呢,我们在实际开发当中用的呢,是比较少的。OK,咱们这块呢,花了一点时间呢,来讲了讲这个set的一个叫无序性和不可重复性,这块呢,其实是为我们后边讲map呢做铺垫的。因为呢,这个set的底层其实就是对应的map。啊,这句话呢,咱们怎么证明呢,其实也很简单,大家呢可以简单看一眼啊,我这块呢,写一个叫哈希set。OK,好哈set这块呢,我们来看一看它的源码,你看哪个版本呢都可以啊,然后呢,我们去new一个哈set,那我们就是使用它的构造器了。你会发现呢,我new的哈set里呢,它声明了一个属性,这个属性呢,一看就是一个map,那哈希set里边就是一个哈希map,那我们new一个哈希set里边呢,他就帮我们new了一个哈希map。
01:04
然后呢,当我们把这个数据添加到哈塞里边的时候,那其实就我们调的这个艾方法了,你会发现呢,它其实就把这个数据呢,添加到了我们对应的map里边了。Map当中的这个添加方法叫做put,而且呢是把这个元素添加到了我们这个map里边,我们叫key和value,放到了我们的key的位置了。Value这块呢,一看呢,它其实就是一个全局的敞量了,是吧,它呢是就new了一个object,就确保呢,你这个value呢,不空啊就可以了,就是给你一个对象,但是实际上这个对象呢,我们也不关心,主要呢,关注的就是这个map里边的key,那如果只关注这个key呢,其实就相当于一个一个元素了,所以呢,我们如果只看map中的key的话呢,它其实就是一个set。所以呢,我们讲set呢,其实是为我们后边讲map呢做铺垫的,所以这块呢,大家理解一下就行,后边呢,咱们讲map呢,还要详细的把这个元素添加的过程呢给大家呢写出来,而且大家呢还需要呢去理解,必要的时候呢还得记一记,因为有的时候笔试面试的时候会考这个问题,OK啊。
02:10
好,那这儿呢,我们就说完了,然后关于这个哈希set和link哈希set我们在刚才讲啊,就是昨天讲到这个无序性和不可重复性的时候呢,提到过呢,要把这两个方法呢做一个重写,因为呢,我们在添加的时候呢,都要用到这两个方法,呃,这个大家记住一下这个结论就可以了。好,那么接着的话呢,我们往后看这呢,就提到了一个叫tree set。嗯,OK,前面的话呢,我们是以这个哈赛的为例呢,说的这样的一些特征,然后呢,另一个哈伊赛的呢,是在哈赛的基础上呢,又加了一对这个指针啊,我们叫双向链表也可以,就确保呢,我们是能够记录你添加的一个先后顺序,这样呢,我们便利起来呢,就更方便了,而这个吹塞的呢,它呢使用的底层的结构呢,跟前面两个呢就完全不一样了,Tree呢就是一个树,其实呢是一个二叉树了,二叉树里边呢,有一类典型的二叉树呢,叫做红黑树。
03:01
啊,这块呢,我们在添加元素的时候呢,需要去比较这个元素的一个大小了,进而呢,我们可以实现呢,按照指定的元素,它的一个大小顺序呢,进行排列的。而这元素的话呢,其实我们都知道往这个set也好,Collection也好,里边添加的都是对象了。所以呢,我们这时候呢,添加元素既然能够大小排序了,那就需要比较对象的大小了,只要呢比较对象的大小了,咱们前面提到过这API了,是不是得需要跟这个比较器打交道了。对,所以这块呢,我们在吹赛当中就需要用到比较器,所以这块大个大家呢,注意一下这个重点啊,咱们现在讲一下这个吹赛,这个重点呢,其实不在吹塞的本身,因为我们在开发当中啊,其实用的还是比较有限的啊,这个重点呢,还是以吹塞的为例,咱们再复习一下关于两个比较器的使用。好,那这块呢,咱们就在这个赛下边呢,新建一个。那咱们就关于这个tree set来做一个说明。行,知道这个重点是什么啊,首先呢,我们写个单词方法。
04:03
哎,行过来啊,这是第一个。OK,行,那既然呢,我们想演示这个吹菜的,咱们首先一上来的话呢,就造一个吹菜的一个对象了,哎,这我们就拗一个这个对象,嗯,然后呢,我们光标往这一放,奥特加回车,诶这呢,我们就创建了一个set。好,然后接下的话呢,我往这个赛里边去做一个添加,这个添加的时候呢,咱们先拿现成的,比如说字符串,我们做一个演示,这呢,我就随意的去添加一些具体的字符串信息了啊,我们来一个诶复制啊。Ad,比如说A。美眉是吧?哥哥。扫扫扫啊行好,这样我就添加了一些具体的字串了,诶添加完以后的话呢,注意啊,我其他的也不用做,我直接呢就开始去便利一下咱们当前这个tet了,那直接呢,我们可以用一下比如迭代器。哎,这个再回忆一下这个叠加器的一个使用。Has next。直接打印呢,点next就可以了是吧,好这时候你看一下啊,我们添加的时候呢,是有一个顺序的,然后我们在遍历的时候呢,你发现呢,它就能够按照我们字符串默认从小到大的顺序呢进行排列了。
05:13
哎,这个呢,就是我们要说的点,那为什么能实现这样的特征呢?其实还是因为我们这个字符串天然的就有一个自然排序。就因为它实现了一个comparable这样一个接口了,是吧?所以这块呢,就能够排序了,好这里边儿我们说一下这个注意点啊,首先的话呢,我们添加的这个元素,咱们刚才提到了说能够实现排序,因为呢,我们对应的这个字串呢,实现了comp接口,那如果是在这个情况下呢,你说我现在呢再去艾特。因为呢,你看这个位置呢,它其实提示我们添加任何对象都行啊,但是你说我们能不能这个时候呢,在。非里边添加一个非字串类型的一个对象。比如这块肯定是个装箱了,对吧。这不用多说啊,那如果我们要用哈希赛的话呢,其实没问题。哈塞的话呢,我们可以放是不是不同的这种类型的是吧?当然呢,我们放到吹塞这块,大家觉得有问题吗。
06:03
哎,我说有问题,为啥呢?因为你看啊,我们前面这个呢,是不是都要比较大小啊。你比较大小的话呢,多少你得是同一个类型的吧。是吧,你同个类型咱们都有共同的属性,比如一会儿呢,咱们演示,比如我有一个person是吧,你这都是person了,咱们必须还是年龄,那大家都得有年龄啊,你这块扔进来一个123,那你年龄都没有。所以这块呢,对于吹赛来讲啊,我们在添加的时候呢,必须得是同一个类型的对象。当你要添加不同类型对象的时候,它就没法儿比较大小了,所以这块我们会抛这样一个叫class class的exception。啊,String这块说转不成是吧。哎,他为什么不说顿转不成阴sir,而不是阴转不成顿呢?是吧?发现了吧?他说string转化不成。按说不是你硬劲过来给转换成顿吗?哎,这个是这个原因啊,就是我们在添加一个新的元素的时候啊,它是拿着你这个元素它所属类的,这不是自然排序吗。
07:01
哎,有个compare to的方法是吧,这个咱们inter里边呢,它也实现了compareable。接口了,它也有这个compare to方法,他在调我们这个inter compare to方法的时候呢,他把你之前这个元素呢,放到那个compared to的醒餐上。哎,所以说这块呢,比如我们这个SS也是一样啊,我这呢是一个字符串类型,我这个字符串找我string里边的compare to,把你前面这个呢往形态上去放。诶,所以这块呢,它是把词缀呢,放到我这个compared to的擎仓了,所以呢,就说你转换不成我。哎,这个注意啊,就填谁呢,是按照谁所在类的compare to方法呢进行的一个比较。哎,这块我们得把它逐掉啊,这个呢,我们说会报,诶class cast exception,哎这样的这个异常信息。好,这个呢,就是我们要注意的这样的一个问题了,OK啊行,那么由这个出发呢,其实我们下一章呢,讲泛行就更有必要性了,因为呢,我们在吹赛当中,那它呢,在添加的时候呢,没有任何的限制啊,说你随便放,只要是我带的就行,但事实上呢,我们必须得是同一个类型的对象。
08:04
所以呢,你看在编译的时候呢,并没有给我们相应的提示,所以呢,从这个角度来看,我们必须要引入下一章的泛型啊啊来限制呢,我们添加到吹塞当中元素的类型。OK啊行,这块我们简单来说一下,这个吹态使用,首先呢,它底层数结构啊,这呢我们提到叫红黑素,因为呢,它使用这个红黑素在添加元素的时候呢,需要进行大小的一个比较,所以这块的话呢,我们就能够实现啊刚才提到的一个特点。那这块提到的啊,说呢,可以按照添加的元素指定的属性的大小顺序进行便利。那刚才呢,因为咱们是自然排序用的是string string的默认呢,就是按照你这个呃,字符串的这个大小顺序来了。啊,这是添加的一个顺序,好,那么通过刚才我们这个演示呢,也提到了一个添加的元素的一个要求,啊,这个要求的话呢,就是。哎,要求添加到。啊,这个。哎,中的元素啊,必须是同一个类型的这个对象,哎,否则,哎汇报刚才,诶,刚才我们看到这个class cost。
09:10
Exception啊,这样的一个异常。OK啊,这呢是我们对应的这样一个要求,好了,这个呢,我们说完之后呢,咱们再回过来这儿呢,针对的是润天然呢,它就已经有一个compar了,那下边呢,我们来看一下我们添加自定义啊这样的类的这个对象了。那这块我们再去新建一个。比如说这个呢,我们就叫做user了啊,在这里边我们去声明类型的name型的age,接着提供构造器。哎,过到期呢,我们就先来一个空餐的。啊,来一个这个全餐的。诶,没问题是吧?好,盖赛方法呢,暂且就不写了,然后我们再来一个to string,诶这个没问题,好,那么现在呢,我要把这个user类的对象放到咱们吹set当中,那大家可能也会想,诶,放到set里边,按说呢,都应该要重写两个方法是吧。这个呢就叫做equals和哈code了,那咱们就next他们都参与啊,好这块我就create了,嗯,这个呢我就写上了。
10:07
写上以后的话呢,呃,咱们也可以在这个位置呢,比如说我们加上一个输出语句啊,这是user的。哎,它的ES方法啊,这个写大目的呢,我们看看它会不会掉啊,这样的一个场景。行,那暂且呢,我们就写成这样一个程度,写完以后的话呢,那么回过来现在的话呢,我们考虑呢,把这个user的多个对象呢,放到咱们吹赛当中看看行不行啊。第二个。哎,那这块呢,我们放的话呢,首先还是把这个吹side呢,你得创建好,哎,CTRL一下。创建好了是吧,然后下边的话呢,我们去创建多个这个user对象,把它添加到咱们这个S当中啊,这个咱们就创建一下啊。哎,User这个呢,我们就相应的给大家起一些名字了。哎,这样,然后我们来五个吧。U23。是。这块呢,就起一些名字了啊。
11:02
Your Tom Jerry。肉丝。杰克。再来一个托尼巴。好,然后这个年龄的话呢,你看我们这块调一调啊。13。我整一个年龄一样的。好,然后这块呢,来一个33。啊行,我就随机呢写了一些这个数据了,好写完这五个对象以后呢,下边呢,我们通过set点的方式,咱们把这几个对象呢都加进来。345好进来了,进来以后的话呢,下一步我们就是做一个便利,这个跟原来一样,我就直接呢粘过来了,行,整个呢这个逻辑呢比较清晰,那我现在要去运行的话呢,会有问题吧。啊,没问题啊。有问题吧?对,咱们说来吹菜的话,你不得涉及到排序嘛,是吧,这个我们是不是也没指定排序方式啊,换句话说,你这user也没有实现compable接口吧。
12:00
对啊,比较大小的话呢,就跟两个比较器相关,现在呢一个都没出现,所以呢,我们去运行的时候呢,就会出现问题。对说呢,我们这user呢,不能够转化成叫comparable,哎,这不是跟咱们前面讲比较器的时候呢,如果呢,你要是没有实验这个接口报的异常是一样的啊,当初出的也是这问题,所以说呢,我们要想往这个吹塞里边呢,去添加这元素,这个元素呢其实是有要求的是吧。OK啊,所以呢,这里边儿我们先演示第一种啊,所以在这个位置呢,其实又涉及到了两种排序方式了啊,那吹塞这块呢,这块我们演示的其实是这个自然排序,上边这个呢,其实也是自然排序。啊,因为呢,这个string呢,天然已经实现了啊。哎,自然排序好,这个呢针对是string,这个呢针对是咱们自定义的类,那下边呢,我们就在这个user里边呢,指明一种哎排序的标准了,所以呢,我们去实现一下叫哎comparable这样的一个接口。那就这样就行,好,那实验这个接口自然而然的要重启这个compare to这个方法了。
13:01
哎,回过来这时候我们CTRL挨一下,哎,然后这块OK一下就再重写啊重写的话呢,这呢相当于是不是给出来我们比较一下,说哪个对象大,哪个对象小,怎么样一种标准是吧。哎,这块我们可以写啊,因为咱们前面已经讲过这个事儿了,所以咱就比较直接了啊,可以跟他说,比如说说按照。哎,按照我们说呢,叫年龄的。哎,从小到大,哎,我们做一个排序。好,那这里边呢,回忆一下我们当时怎么写的啊,首先呢,我们写了个衣是吧。哎,跟这个O呢,如果是相等的。那这个我们就return一个零了是吧,哎,否则的话呢,我们判断O是否instance of当前这个user。如果是个U酸钠,先做个强转。诶强转了,强转完以后的话呢,这是我们比较的是他们的年龄,直接呢,咱们就相减就行是吧。c.a值呢,减去一下u.a值啊,减完以后呢,你是正的就是正的是负的就是负的是零,那就是零。
14:02
没问题是吧,啊这呢是你是一个有色的时候呢,这个情况,那要是不是呢,这块呢,也得有一个相应的返回,这呢咱们可以就抛一个异常是吧。比如runtime exception啊叫类型。哎,不匹配是吧。诶这样就可以了,好这呢我就写完了,诶我写完以后的话呢,咱们回过来,那么此时呢,我们再去添加,其实问题就不大了。啊,问题不大了,但是这块呢,你要注意一个问题,就是咱们此时呢,我特意写了一个年龄一样的。年龄一样的情况下呢,如果我们按刚才提的这个标准去比,它俩应该就是相同的了,是吧。相同了会怎么办呢?看一眼。大家看这时候呢,我们里边呢,就只有四个元素了。那说明呢,有个没有,那你细看的话呢,其实缺一个23。哎,那缺二三缺哪个呢?Tom进来了。杰克没进来是吧?捷克这块的话,因为是我们后加的,所以呢,后加的这个就没进来了。
15:01
那按照我们的理解呢,说塞里边呢,是不能够放相同的元素的,那对于这个吹塞来讲。他其实发现就把这个U4认为和U1一样了。你看是这意思吧。啊,因为呢,我们这个年龄一样了,你看就没进来,没进来呢,就认为相当于一样了,所以没进来。那所以呢,你会发现咱们在这个调I的方法的时候呢,你看啊,我们这个user里边,我还特意的在前面写了一个输出语句,你发现呢,他并没有去调用这个E方法。是吧,根本就没比按照咱们你看前面讲啊,昨天咱们不是讲这个逻辑的时候啊说呢,我们在添加的过程当中是吧?啊说呢先哈西扣的,然后在e cos啊那这时候呢,你发现呢,咱们根本就没有调哈扣的和E库方法,所以呢,你看前边这块呢,我写的时候呢。诶是以哈西set及其此类为例,也就是说你是哈西set型另一个哈,也可以按照这个去理解set呢,不适这里边的这个特征。
16:00
啊,包括你看我在这儿啊,大家可能没注意哈,我这块在写的时候也明确写的是添加到哈西set或者是link的哈希set当中元素的要求。没有说添加到set中的要求啊。也就是说呢,咱们写的这个事儿呢,其实不适用于这个ET。就是因为呢,这哥们呢,它底层用的数结构根本就不一样,咱们前面呢是西是一个数组是吧,你往这放啊,第一个在这儿,第二在这儿,第三个在这儿表因为这种叫无戌性了,然后呢,万一有一个呢也在这儿,他俩还不一样啊,那就是这么着了。哎,这叫链表结构了,哎,这呢是哈西塞和另还是赛,而这个吹呢,上来这一个元素啊,跟它一比,比这个小,比这个小我们就往这儿放,诶再一过来跟那一比,比这个大,哎,比这个大我们就往这儿放。他通过这样的方式呢,这不就诶有大有小,有大有小,就这样就下来了。它在这个数当中啊,这是个宏位数,它里边是不能够出现相同大小的元素的。也是我一过来,哎,比,跟着元素一比,比这个大,我就跟他比了,跟着元素一比。
17:00
这个比的话呢,其实就咱们刚才写这个compare to方法了,我一比一样。一样的话呢,注意这个时候呢,就后边的元素呢,就不要进来了。哎,这呢,有这样的一个特征啊,那言外之意呢,大家能够看到哈,这个我们回到这块呢,做一个说明。在这儿我们判断数据是否相同的标准,你发现呢,在吹塞里边变了。啊,我们在这儿说明一下啊,说呢不在。啊,不再是。啊,考虑叫哈西扣的。哎,和我们这个eo的方法了是吧。诶包括呢,这个我们所谓的不再考虑呢,还有一个层面的,比如说我们这个催赛的,它不是实现了赛接口嘛,在里边呢,我们说也实现了这个,呃,也继成了这个莱接口collection,咱们在讲的时候呢,提到过像这个contents啊,Remove啊,诶当时我们讲的时候呢,说他们在调用的时候呢,会涉及到了对象调ECO方法是吧。就说呢,诶看看有没有,有的话呢,就出这个呢,呃,想移除那得先确保有利元素,有利元素我就移除了,注意咱们现在呢,改成吹塞以后呢,它的这个contents和remove方法呢,首先是有的。
18:11
啊,毕竟呢,你也实现这个接口了,你能找对象,你肯定是重写过这样的方法了啊,但是这时候呢,我们判断有没有的标准也不是。哈和E的方法。完全的就替换为咱们现在呢,提到的自然排序和定制排序里边的那两个方法。啊,这个大家一定要注意,不再是考虑这两个方法了,说呢,嗯,也就意味着是。哎,也意味着呢,就是西安加道。啊,咱们这个中的这个元素啊,它呢,所在的类呢。不必要,或者叫不需要。你去重写这两个方法了。就是你写不写呢,无所谓,反正我也不用。啊,就这意思,好,那这个标准是什么呢?我们说呢,比较。
19:03
啊,这个元素大小的或者是。啊或哎,比较元素是否相等的标准。啊,就是考虑这个自然排序或定制排序中。啊,这个一个呢叫compare to方法是吧?呃,另外一个呢,叫做compare方法,他们的这个返回值。啊,如果呢,你要是比较大小呢,你就看这个返回值的大小了,你要判断是否相等呢,就是看一下这两个方法的返回值是否是零。啊,在这再说一句啊,说呢,如果这个这个方法啊,或者是后边这个方法的返回值为零。写这个零吧,诶则认为两个对象呢是相等的。那既然是相等的,那咱们吹塞里边还不让你放相等的元素,那就意味着我们后边的元素呢,就进不去了是吧。
20:00
啊则认为两个对象是相等的,啊则,哎,或者这样说吧,哎,由于。这个吹中。哎,不能存放。相同的元素。哎则哎,我说的这个哎后一个哎相等的这个元素,哎就不能添加到。咱们这个A中。OK啊,就这样的特征,所以呢,通过咱们刚才这样一个演示呢,也看到了,为什么我们这个捷克啊,他呢二十三进不去呢,就是因为呢,我们按照咱们自己的重启的这个标准来看呢,它跟现有的某一个对象的这个哎是一样大小的。哎,就说诶这里边既然是age一样,就算是一样了是吧,哎这块呢,其实这个标准咱们可以自己定嘛,你比如说呢,我们怎么认为一样呢,咱就认为说name跟age都一样才能一样。那你其实只需要是改一下你这个标准不就可以了吗。是吧,比如说这块呢,我们把它呢给注释掉。哎,我先这样复制一份是吧,CTRLC一下,然后呢,我把它注掉,注掉以后呢,咱们再重写一下是吧,你要觉得说呢,光比这个A呢,差点意思,那这块我们可以改一下是吧?哎,比如说我们的先比较年龄。
21:10
啊,这个比如说从小到大。啊,排列是吧。哎,说如果年龄相同。对则啊,继续比较这个,比如说年,呃,姓名是吧。下面的话呢,我们也是从小到大吧。OK。行,这呢就是我们给的这两个标准,那这样的话呢,我们就来看这个位置了,啊说呢,它两个A呢,做个减法,我们在这个位置呢,先给它接收为一个返回值。比如就叫一个Y6吧,判断一下,如果这个Y6呢是不等于零的,那就相当于你不相等,那我们就直接把你这个Y6呢就返回了。啊,那在这个位置相当于就是一个else了啊,那如果你要是相等的话呢,我们就继续比一下你的这个name啊,那就是当前c.name这呢,是不是直接调compare to了。哎,优点name。
22:00
好,这个呢,我们也是从小到大了,所以你就直接return,你要从大到小呢,我就符号一下。诶,或者咱们这块比如说改一下吧,从大到小。哎,体会一下这个不同的啊,好,那这个呢,我就加一个符号就可以了,行这个标准写完以后,那么回到咱们的这个吹塞的这个测试这个层面,我们再来做一个测试,这时候你看这个杰克能不能进来。那就进来了是吧,这时候呢都是23,在年龄一样的情况下呢,我们继续比这个内内呢从大到小排,呃,所以T呢比勾呢靠后,所以呢Tom呢就在上面了。哎,就是这样的一个思路。OK啊行,这呢就说的比较清楚了。这呢,相当于咱们目前使用的叫自然排序。相当于呢,我们一个复习了,那自然排序完了以后,下边咱们看一下这个叫定制排序。OK啊,定时排序,定时排序的话呢,前面咱们已经有这个经验了,相当于呢,跟这个competitor去打交道的。跟competitor打交道呢?怎么打交道呢,或者我们在哪个位置去传一个competitor呢,实际上呢,是在这个构造器当中。
23:03
那我们把光标放在这儿,CTRLP一下,你发现呢,我们可以传一个competitor。哎,传上compare,那你提前把这compare呢给它造好。写个有名的也行,匿名的也可以啊,这呢时间类呢,我就匿名了,然后这个对象名呢,就咱们就起一个了啊,就要compor了,又一个啊。competitor。直接一回车这块就已经生成好了啊好,那么关键点呢,咱们就写这个compare这个方法了。呃,那么接下来呢,你需要注意我们这时候这个O1O2是object类型,那这个具体是什么类型啊。那得取决于你现在想把谁添加到我们这个垂塞的里边是吧?添加到吹塞里边的元素是谁,那这个object呢就是谁,说白了就是你添加的时候你想比较谁的大小啊是吧,这呢就是哪个类了啊好,那咱们还是想把这些user呢添加进来,下边便利呢,我都原封不动的都带上啊。也就是说呢,我们下边呢,其实是想。哎,还是把这个user呢听进来,那进而的话呢,首先啊,你把它呢先传过来,所以呢,这里边儿呢,我们object呢,就应该是user。
24:05
啊,所以这块我们就开始判断说OE user。啊,并且OR2USER。那下边就强转了。哎,O1啊,然后复制一份。啊,U2O2行都是U4的情况下,下边呢,你给个标准吧,啊,比如说在这块我们给一个标准啊,咱们反过来吧,就是先比较他们的姓名啊。按照姓名,比如说从小到大是吧排列。啊,那如果要是性命一样了,你再考虑按照这个年龄排也行啊。哎,如果姓名相同。啊,继续这个。这个叫比较咱们的A。按照比如说从大到小。
25:00
来排列。OK啊行,这呢我们把标准就给了,给了以后呢,我们上来呢,就是u1.compareto这个U2,这呢就得到他们的一个,呃,姓名上的一个比较了啊这呢,我们也得到一个,比如Y6判断一下啊,如果Y6。哎,本身呢不等于零,说明呢,我们这时候就不相等了,就返回啊,那如果要相等的话呢,我们继续比它们的A。直接就return一下U1.a啊,这个A呢,因为我没有加这个private的一个限制啊。所以这块你看我是不是可以直接调。对啊,如果这块包括我们。我这写错了吧。写错了啊。我这儿呢,不能这样写了,这不成了,要我们这个什么了。调我们这个了是吧。对,别调它哈,这个咱们应该是调离内哈,所以这块我们严谨一点把它呢,加上这个private的一个限制啊。这样呢,我们私有化以后呢,我们在这个位置啊,提供一下盖菜方法。
26:00
那这样呢,咱们给它加上啊,OK,没问题了,行,那么回过来这个呢,本身写的也不对啊,咱不能这样掉了,哎U一点,哎,我们就要get一下name是吧。然后比较它的一个compared to啊U2.get个name啊,这呢是比较这个姓名的姓名要不一样呢,直接返回姓名一样呢,我们这块点get一个age是吧。A呢,因为本身是int类型了,咱们就直接做减法了。Get一个A,诶这不就妥了吗?但是现在呢,他要求呢,是按照它的从大到小排的前面这个从小到大真没问题,这个呢括起来。诶前面呢,整个符号,诶这样就妥了。这就从大到小了,行,那么这块呢,咱们啊还还有啊这个衣服呢,万一要没进去呢,还得给人抛个一场。Runtime exception。类型不匹配。诶这样好,那么这个对象呢,我们就创建好了,把这个对象呢,放到这里边,然后呢,你就可以往里边去添加了,添加的时候呢,我们就按照你给的这样一个标准呢,我们去比较了。
27:03
行没问题,这块呢,我们是按照这个姓名来进行排序的,来跑一下啊,尤其。嗯,看这块儿就可以了,这个呢,诶勾2T是吧,然后里边呢,是从小到大的顺序来啊,因为呢名字没有一样的,所以这块呢,其实A这块没有出现个比较啊。好,这呢,就是咱们说的这个叫定制排序了。啊,这个大家稍微的注意一下这个问题啊,其实你会发现呢,就是当我们这呢,咱们是用的叫tree set来演示的,前面的话呢,咱们是用的AR是吧。在讲这个比较器的时候呢,咱们因为当初没有讲这个集合嘛,所以呢,这块在演示的时候呢,我是拿这个aris来演示的。这个时候呢,你会发现呢,不管呢,是A瑞也好,还是我们这个吹赛也好,包括呢,我们这一章后边呢,还会讲这个CLA是吧,这样一个工具类,工具类里边也有相关的排序的操作。只要涉及到排序了,是针对对象排序的,那我们都是跟这两个接口打交道。啊,这个可能有的同学还针对这两个接口有点迷糊啊,你也不用想那么多,你就这样哈,还有一个小技巧,就只要你调离方法的时候呢,你要是发现呢,需要传一个competitor。
28:10
有位置让你传一个competitor,那这肯定就是定制排序了呗。是吧,那你就提前的临时你给他造一个competitor,如果呢,没有出现这个competitor,你像我们这个瑞这个呢,去调so方法的时候呢,你把这个去掉,它不也有个这样的重载的方法吗。那它呢,就是用的自然排序是吧,就是按照你这个里边ARAR你看你是啥了啊,你这是product好看你product有没有实现这个comparable了。诶,就是这样一个逻辑啊,这个咱们给大家还加上啊,再回到咱们这个吹塞这块呢,也类似啊,在我们一开始上边我用了个吹塞的里边没有任何位置放这个competitor,那这个时候呢,你放的是user,那user呢就是用的自然排序。那你要是有位置能给他放一个。那这个comp了,那这种很自然而然的就是定制排序了。就这样的小技巧。OK啊,那又因为呢,你放这个command呢,我可以造好几个command对象,让我想放哪个就放哪个,杨爱之呢,就是你这个比较大小的标准呢,可以非常的多样嘛。
29:08
是吧,诶这呢也是我们说的compare的主要特点啊,它就比较多样,比较灵活,而你要是不写它呢,那就只能是自然排序,而自然排序呢,U呢早已经写好了,你也动不了,你只能是按照人家给的这种方式来,所以呢,它是比较单一的嘛。这不就引回去咱们说的他们二者的一个特点了吗?哎,就这样啊。好,那么关于吹塞的呢,咱们就完事了啊,回过来这个位置呢,其实可以多写一个事儿,另一方面呢,是要求得是同一个类型的对象了,诶第二的话呢,就涉及到了我们添加的这个元素。哎,添加这个元素呢,哎需要呢考虑哎这个排序是吧,这呢我们就讲了两种方式自然排序。啊,第二种定制排序行,这里边儿的重点注意啊,咱们吹ET呢,可能大家很少去使用,但是呢,这个排序呢,我们是肯定要面对的,所以呢,重点不在ET上,而在于排序上,相当于通过吹ET呢,大家再去熟悉一下两种排序方式。
30:05
这个呢,注意一下好,那么这样的话呢,关于这个吃菜呢,咱们就告一段落,接下来呢,大家也可以写一写。OK,那么我们关于set的话呢,讲到这块,其实呢,基本的知识点就告一段落了啊,这里边儿的一个难点呢,其实就是关于set当中的无序性和不可重复性的一个理解,注意这两个的理解,咱们提到了一个叫哈西扣的方法,一个叫依扣方法,这两个方法的重写呢,不涉及到。黑。是吧,诶因为吹塞本身咱们用的也比较少哈,这个在赛里边呢,主要的时间内是哈西赛,所以咱们这个呢,主要说的还是哈西赛啊。像咱们刚才里边呢,讲到关于吹赛这user里边的这两个方法,咱们其实完全可以把它们注释掉的,因为你是添加到吹塞里边了,跟我们的这个呃ecos和哈ECO呢,其实是没有关系的。啊,这个大家注意一下。嗯,好,这个呢,我们就告一段落了啊,然后回过来的话呢,我们看一看这个sat的课后练习题这块有两个,还有一个。
31:02
第十题是吧?好,来看看第一道题啊。说呢,定一个如下的方法。这个静态方法dulicate,然后list这个list,这个list里边呢,它会有一些重复的数据,它要求呢,我们在调完这个方法以后,返回一个list,这个list里边呢,就没有重复的数据了。言外之意呢,就是重复的数据呢,你只放一份,不要放多了。哎,这样一个情况,那这时候我们就相当于呢,要过滤一下重复数据了啊。既然呢,放到我们set这了,是不是就考虑用set来做一下。OK啊,哎,零一是吧,这个题哎,写个没方法都可以啊。好,把这个方法写到这儿啊。好,这个例子的话,因为不同的包下都有咱们需要显示的导一下啊,U下的别导错了啊。呃,这个是这样一个场景,比如说我们先去new一个啊叫A。哎,先扭个它out啊,回车先来一个list吧,行,这个list子里边呢,我们去添加一些元素,这呢,不妨我就拿这个,呃,先写成in的类型,其实呢,就自动装样成了啊,先整几个就是一样的。
32:10
再来一个,比如说22,哎,再整几个一样的。嗯,45,哎,整俩一样的行,就比如说这个吧,现在呢,我把这个例子呢,放到我们这个方法的形参的位置啊,我就要调这个方法了。哎,这呢,因为静态方法就可以直接呢这样掉了啊好调完以后的话呢,它就得到一个新的一个list。啊,我就声明成list了啊,这也没事儿,哎,新的一个list,那么这个list啊,假设我就直接打印了啊,对吧,你有一个list在打印的时候呢,你里边就像34呢,就留一个,22呢也是留一个,45呢也留一个。哎,这样的一个情况,咱们过滤掉重复数据啊,怎么做。想到用set是吧。呃,那么我们要不用赛的话呢,那就是你自己呢,是不是考虑诶,只要发现一样了,我们就。不要了是吧,现在你在这里边可以去新造一个a list,然后呢,去先把第一个添加进来,添加第二个时候呢,跟第一个比一下。
33:04
看一样不一样,不一样就进来,哎,如果第三个呢,跟前面的都比一下。都不一样了就进来,显然呢,这样的效率呢比较低是吧。对,而我们这个set呢,注意它来过滤重复数据,它用到了这个,咱们昨天提到的叫。哈希算法是吧。其实这个算法的一个核心想法是什么呢?就是我们要是一个一个跟之前去比的话呢,这个显然是比较慢的是吧,我们怎么办呢,我先给这个对象啊算一个数。咱们先看这个,大家这个数一样不一样。对吧,数要不一样的话呢,就省着去掉一扣的方法了,是吧,当然这个数一样不一样,你说哎这不也得一个个比嘛,咱们这块呢,就考虑呢,咱们,哎,如果这个数呢,一样也好,不一样也好,咱们都放在一个数组里边,放在某个位置,比如呢取模一个16啊,这个16呢,主要是比如说数组长度是16,那我就取模16了哈。好,曲波失以后呢,它这个值呢,就是从零到十五零范围内了,哎,我呢就把你放到某个位置。
34:02
然后呢,你别的这个数呢,算的时候呢,假设数跟我不一样,自然而然你放的位置呢,可能跟我就不一样。这块有点难度啊,咱们再说两句,就是我现在算了个数,这个数的话呢,你要跟我这个数不一样。啊,挺大的概率呢,就是你放到别的位置了,但是也有可能咱俩数不一样,是不是一取模16余数一样。于汝阳,那就也过来,你过来呢,是不是咱就管往咱俩比一下就行是吧,你就用不着跟别人比了嘛,这就大大的降低了我们去比较这样的一个成本。这就是他的一个核心的一个想法啊,OK,这样一个思路,行,那我们现在呢,就用这个set呢,显然呢是比你自己比呢要靠谱的多啊,自己比呢,这个复杂度是比较高的啊,那我们需要把list中元素都添加到咱们的set里边。怎么办呢?点了一下是吧。啊,那得先,咱们先造出一个哈希赛吧。哎,New一个,哎,咱们的哈希set这么着写的是吧,然后呢,我们写一个比如说增强for循环吧,哦债类型的obj,然后冒号一下,这个呢,就是list色呗。
35:10
然后呢,特点艾特一下啊,我们这个obj是往里一顿加就行。加的时候呢,如果要一样了,它自动就给过滤掉了。啊,因为呢,这里边儿他已经都重写了ES和哈西code了。哎,像这个常用的这一类呢,都已经重写过了,那你一顿加完事了,那接着呢。他现在要的不是赛是吧?它叫个list,你想现在呢,我们这个set呢,该怎么转化成这个list。哎,再遍历一遍是吧,就相当于呢,现在呢,我们得是不是又得重新新造一个A。对,我一个。啊a list是吧,然后呢,我们再去明一下啊,List这叫LIST1,比如说啊,然后接着的话呢,你再把这个set的元素呢,一个个再变历一下,再。放到我们这个例子里边是吧,这呢还是我们这类型,我还叫接这个呢,针对的是我们的set。
36:02
然后呢,拿着这个list一点,我们艾把我们这个OB呢再添加进去,然后最后呢,我们称一下这个LIST1。哎,得这么着是吧。OK啊行,然后呢,回过来我们再去做一个run。哎,这时呢,我们就自动的过滤掉了这个重复的数据了。行,这个题呢,就这样写,如果呢,这个位置写的话呢,感觉似乎有点长是吧,把它注掉,这呢算是第一种写法。哎,方式一啊,呃,稍微的简便一点的。注意我说的这个简便呢,指的是从我们编写的角度来看,是简便一点的啊,怎么着呢,我首先呢,有一个哈塞,这个没问题啊,只不过呢,这个哈塞的这个构造器当中,CTRLP一下,它支持我们放一个collection。那我就可以呢,把这个例子呢,直接就扔进去了。啊,它怎么做的呢?其实你看一下源码呢,也非常的清楚啊,诶这块,诶当然这个你就不用多多看了啊,就看这啊,我们把这个它叫collection at all at all,其实咱们都测试过了,不就把这里边呢都编了一下添加进来吗。
37:01
是吧,哎,其实呢,跟我们刚才这样写法是类似的,只不过呢,不用我们自己写了而已,好,那这样的话你就生成一个类,呃,生成一个set了,里边呢,就自然而然的是没有重复数据了,那我们接下来呢,是不是再去一个例子。另外一个release的时候呢,我再把这个set呢,我也进去。同样的思路啊。哎,我这块呢,直接return下一。那就可以了,哎,就是你看似呢,这块比较多,这块比较少,其实里边的逻辑是一样的,只不过呢,不用我们自己写了而已。好,然后这块我们做个return,回来呢,我们再去做一个run。啊,也照样没问题。行,这道题呢,我们就这样写就行了啊。好,这个完了以后呢,接着来看第二道题,这样写的,说编写一个程序,获取十个一到20的随机数,要求随机数呢不能重复了,然后把这个数据呢,输入到控制台上,不能重复了,像以前的话呢,咱们呃,记不记得以前写过说那个。就那个彩票是吧,呃说呢生成啊这个,呃六个数的一个数组是吧,然后这里边儿这个范围呢,是一到30,要求呢不能重复,当时咱们咋考虑呢。
38:08
填一个是吧,这个没事,第二个得跟第一个比一下。第三个得跟前两个比一下,这个咱们得自己去处理这个是否重复的问题了,现在呢,如果我们要有赛的话呢,这个事儿就非常的简单了,是吧。这个逻辑呢,他都给我们控制好了啊。我来。零二。哎,这么着啊,没方法进来。把这个需求呢往这一站。嗯,那自然而然的话,我们这块呢,就是new一个哈希set呗。这个前面的话呢,还是这个道理啊,我写个set呢,其实就是省点事是吧,哎,完全没有必要用这个多肽的啊。好,然后呢,我们往里边去添加嗯,一到20的随机数,先把这个呢,先弄出来s random去乘以一个。呃,一到20包括这个边界,那20减一加一是吧。20减一加一,然后呢,这块出来以后呢,再加一个一这样的。
39:04
这儿呢,我们来一个int类型。啊,后边这块一定要包一下啊,要不包的话呢,他们就先运算了,这个结果就成零了啊。这个包的话呢,至于说你是包到这儿还是包到这儿,其实都可以。嗯,这都没事儿,行,这呢相当于我们得到一个随机数,比如就in型的叫random吧。这个随机数的话呢,我们一共要取20个啊,啊不是取十个。那取十个,然后还得把它添加到咱们的这个set当中。这么着是吧,那这块我们这个循环怎么写呢。你要写for也行,但是这块你注意一定不能写十次是吧。对,我们这个判断条件呢,应该是不是十次,应该是呢,我们这个set中有十个元素。对,所以我们这块比如写成while吧。s.S如果要是小于十等于,能写吗?
40:03
等于不要写了,等于你要再写进去,不就成11个了吗。哎,你要小于十的话呢,那就进去生成一个随机数,添加一个走走走,直到呢,你这个不满足的时候,也就是十个了。就退出了,那就说明里边就添加了十个这块呢,如果你要是得到的随机数呢,是相同的,自然而然的就没加成,那你就size也不会变是吧。哎,这样的啊,好,出来以后呢,我们来一个呃,E。然后while has next。啊点next,诶输出一下。哎,输出一下啊好走起。哎,这呢就出来了,这里边儿呢,这十个数呢,它一定不能相同。相同的就出问题了是吧,不会的啊好呃,这呢你也可以呢,有一个稍微的变态的一个想法。什么想法呢?我要让它生成十个比如一到十的随机数。那就相当于每个数就得出现一次了,是吧。
41:02
一到十的,我把这个位置改成十是不是就行了。哎,走起。你看这时候呢,是不是每个数都得出现一遍看。行,那我这块呢,再变态一点。一到九的随机数。这个呢,是不是就臣妾做不到了,就。是吧?啊,这个呢,是不是就永远接受不了了是吧?对啊,一到九的还不能一样的,然后呢,你要求产生十个,那有点扯了是吧,所以呢,这个就接受不了了,哎,说明这个程序写的没问题啊。好,这就过了,然后呢,咱们再来看一个笔试题啊,一般呢,说到这种笔试题的话呢,都得紧张一点啊。比较阴险一些。诶,这个题目的话呢,大家你看一看,是否对咱们提到的这个哈希code和E方法有比较好的理解。啊,这个题目呢,稍微有点难,这个呢,我们到map的时候呢,看源码的时候,还会再讲一讲它的彻底呢,就把它弄清楚。这个题目呢是这样子的,我们有个person,这个person呢,里边有属性扩大器,注意把equals和high呢都重写过了,这个呢也是自动生成的,所以呢它是一致性的啊,这个你就不用担心了,回过来以后注意看啊。
42:13
这呢,是一个哈希塞。了一个person,又了一个person,他俩呢,你看不一样哈。然后呢,添加添加问几个。这就俩了是吧,好,我们先把这个除掉啊,一点点来运行一下。俩没问题啊好,然后接下来的话呢,有这样的操作啊,我把这个P1的name呢,改成了CC。P1的name改成CC了哈,然后呢,Set一下一下P1。打印一下。问,这时候呢,还剩谁?这一一上来就就就有点儿整不动了是吧。哎,走一下啊,运行发现没有山城是吧。
43:01
啊,这个呢,能不能理解。啊。这块来稍微的说一嘴是吧,诶这块呢,咱们知道这个哈塞的底层呢,是一个数组的结构是吧?诶那么一开始的话呢,我们P1也好,P2也好,先呢计算他们各自对象的哈希值是吧,这个哈希值呢,然后呢,在比如说是个曲目的操作,诶看看你在这个数字中存哪个位置啊,这个位置的话呢,比如说第一个叫P1 p1呢,不用说了,肯定能进来,然后P2的话呢,这个我们说概率比较,从概率上来讲啊,比较大的可能性它应该。不大可能放到这儿,但是也有可能是吧。P2,有可能跟他放一起吧。有可能就是他俩还一直不是不一样吗?但是呢,万一要是取模16的话呢,是不是余数一样。也有可能是吧,于说要一样的话呢,就是它也要放这儿,但是它也要放这儿,接着呢,你去比较哈一指哈一指又不一样,其实他俩就先后就放了是吧,但是这种可能性,毕竟这是好多位置呢,相对来说小一点,咱就先哎就当一般的情况来考虑哈,哎,他在这儿,这是这个P1了,然后P2的话呢,假设咱们就在这吧。
44:05
所以呢,他俩就都进来了啊,他俩都进来以后呢,接下来我把这个P呢点内呢改成叫CC了,注意咱们其实这是个地址值啊,它实际上指向的是一个对象了,哎,1001,现在改成CC是吧。诶改成它了,这个呢还是1002BB,然后呢,我现在remove一下P。一下这个PPE1的话呢,它是个地址。咱们remove的时候呢,在set当中,不管你是添加也好,Remove也好,都得是按照咱们哈希code和E这个顺序呢,去找到这个元素,然后呢,哎,确实一样了,你要添加呢,那就不要进去了,你要删除呢,那就把它删掉。所以呢,这个瑞和A呢,都要去按照我们哈西扣的ECO的这个顺序来来的哈,所以呢,我们要删除这个P,我是不是需要呢,计算你这个P这个地址所对应的那个实体里边的哈西扣的值啊。我一算哈值,注意这时候哈一值呢,是拿着1001CC算的。
45:00
那算完以后的话呢,我是不是就开始去这个数字里边找,如果要是添加的话呢,你这个100CC应该放哪去那个位置是不是找这个元素啊。那找的话呢,是不是就找不到这儿了是吧。找不到这儿的话呢,假设呢,那个1001CC呢,可能要存的话,就要存这儿了,那一找这个位置是没有。没有是不是就没删成。当然也有同学会说,诶,那要万一的话,我们要找这个含义值呢,要计算,诶跟那个P1的含义值注意不一样了,P这个含义值呢,咱们是当初是1001A算的啊。对,你要是这个新的这个拿着1001CC去算的话呢,呃,那也有可能这个元素万一要是存的时候呢,也有可能是不是存到这儿。有这种可能性啊,但是他要也存这儿,现在删的话,是不是也得是这个逻辑过来,那这时候呢,我们就要看一下他俩的含义值一样不一样了。注意这时候P1咱们说了,它的含义值呢,是1001A的啊,你呢,现在是101CC算的含义值,咱俩含义值不一样,说白了就是都没有机会呢,去调一库的方法,咱俩呢就算是不一样了。
46:04
所以呢,这个还是没删除。注意,所以这块呢,还是两。哎,注意还是两啊行这呢,我们不是有这样的一个场景了,哎,我我就就不保存了啊,好在这个情况下呢,我们再来一个爱的。我添加一个1001CC啊,不嫌事儿大是吧,又加一个,他问能加进去吗?你看已经有101CC了是吧。对,你发现呢,我们在执行的时候呢,他竟然进去了。可能诶,你这里边儿都已经重写这俩方法了,怎么这块还能进去重复的元素呢。对,因为呢,呃,这个咱们这这这这已经看不出来哪个是哪个了,是吧,就是原来你这个1001AA的那个变成CC的时候,你用的它一直呢是。A的是吧,所以呢,你这俩里边呢,相当于哈希值是不一样的,哈哈,值不一样,其实根本也没有去调那个ES。
47:01
没机会是吧。哎,注意言外之意啊,你看这块回来,我在这个位置上,咱们比如来一个叫person的equals,诶点点点,我这样加了一句是吧。好,回来以后呢,我们再去run一下。大家看是不是根本都没有掉。说明根本就没有给你机会去调一斯,因为哈希值本来就不一样是吧?有点难度了啊,好,再来一个。我呢,再添加一个person,我叫1001AA。能加进吗?加不进去了是吧,对吗。能是吧,走起。诶进去了,诶这块看到它掉了是吧。诶对了啊,这个时候呢,相当于我们在加的时候呢,它算了哈一值,它跟咱们最初的那个西一那个哈一值一样是吧?哈值一样,但是咱俩接着呢得ES了,是不是就ES了E时候发现咱俩还不一样啊,你是10C或幺零。
48:06
但是还不一样,是不是又进去了?哎,这个题呢有点意思啊,这个的话呢,咱们就先不debug了。啊,为啥呢?因为我debug去看的话呢,咱们说了赛的底层是map嘛,所以我们其实这块还没讲map,所以呢,我们就不太适合先debug了,那我们这个讲完map以后,呃,咱们讲第14章讲源码,把源码这块呢说清楚以后呢,我们再来看这道题,大家呢会对他彻底的弄清楚,暂时呢,如果这块还不清楚的,呃,这个愿意再看一下也行,或者你再放一放也行,后边我们讲完源码第十项,我们还会再提一下它啊。
我来说两句