00:00
大家好,我是海波老师,我们继续来讲Java集合中的哈希赛,之前讲过啊,哈希赛的集合中不能存储重复数据,但是咱们之前给大家演示的呢,都是一些字符串啊,什么ABC啊,什么张三李四王五啊,现在我准备创建一个对象往里面放啊,那么咱们看一看,来我们把这个关掉,关掉以后呢,我们来拷贝一下来,我们写上一个二。点击OK。然后呢,把里面的东西啊,咱们都去掉,现在呢,我准备一个对象,咱们叫class啊,咱们叫U9,好了,写完了以后呢,我在里面添加两个属性,一个叫ID,一个叫name。好了,我们写上它啊,咱们叫做使君啊,咱们叫做name,行了,然后呢,我们再重写它的一个方法,咱们叫做突使菌方法,所以呢,把这个突菌方法给它重写一下,重写以后啊,咱们这里直接返回什么呢?我就返回咱们当前的U,哎,给他一个我们的ID。然后呢,再来我们再写上它啊,咱们再来写上这个东西,我们叫做name就可以了,好了,写完了以后,现在干嘛呢?我准备创建几个U的对象,往这个集合里面放一下,所以呢,我就写上它,咱们叫U的九啊,然后呢,叫U的啊我们的一,它等于new咱们的U的九诶是这样的啊好了,我们写完以后呢,我再写几个啊,这里写成一个二,写成一个3AOK,写完了以后大家看一下啊,我现在这样,我们的这个U的一啊,点我们的ID呢,我的等于1001,然后呢,U的1.name,它等于张三对吧?哎,咱们这么写,写完了以后呢,把这个呢,我们复制一下,然后呢直接复制,然后拷贝到下面,我们这个U的二呢,它里面的ID和我们的名称完全相同,是一样的,然后呢,我们接下来拷贝,拷贝以后呢,往下放,这个呢,咱们叫三,然后呢写个三,然后呢,我改成什么呢?二改成李四。
01:52
这样的话呢,我们就有三个对象,但是前面两个其实是相同的,为什么呢?因为1001相同,张三相同,所以他们是相同的嘛,好了,把三个对象呢,往里面放,咱们来增加我们的这个叫U1,然后呢,来复制一下好了,把这个改成二,把这个改成三就可以了,行了,那么改完了以后,那么我们说过了,你第一个这个UR和第二个UR啊,相同啊,对吧,都是一样的呀,我们这里呢,就准备去打印一下,看一下我当前的集合对象里面到底有多少个对象,我们这里啊,我们说了,我们前两个对象呢,它们都是一样的,为什么呢,都是1001,都是张三,我们的第三个对象它不一样,所以咱们打印运行看一看。
02:31
运行之后呢,大家会发现诶。我们当前的张三两个都有啊,李四也有啊,所以当前我们集合中的对象其实是三个对象,对不对?哎,这个跟我预想的不一样啊。不是说数据不能重复吗?那我们这里两个对象1001和张三它不就是一样的吗?怎么还是存进去了呢?那这样的话跟咱们前面讲的不就不一样了吗?其实啊,这里不对的原因主要在于我们认为这两个张三对象是一样的,那只是我们认为,但是我们的哈希塞的集合并不会认为它俩是一样的,他认为这两个对象是不一样的对象,哎,这是怎么回事呢?这就是我们判断标准的不同了,咱们认为这两个对象只要其中的两个属性是一样的,这不有两个一样的对象嘛,对不对?但是在我们的哈希set眼中啊,你的这两个对象啊,是两个独立的个体,他们在内存当中啊,它们是独立保存的,所以啊,他们的内存地址它并不相同,那么这里的地址呀,我们一般指的就是对象的哈希code的值,大家看一下,我们来找一下,咱们这里呢,打印一下叫U一点哈希code,然后呢,我们再来打印我们的这个第二个对象呢,咱们叫U2点哈希code,诶这个哈希code的值呢,我们可以简单的类比。
03:43
为我们这个对象在内存中的地址,所以我们运行,运行以后,大家看一下我们当前的两个地址是不是不相同啊,你不相同的情况下,它会认为这是我们的两个不同的对象,这个大家能不能明白,既然是两个不同的对象,那你说它可能放在我们同一个位置吗?它就不太可能,对不对,所以啊,这就是为什么我们的集合中有三个对象的原因了,就是因为这两个对象其实它并不相同,这个大家能不能明白?好,如果能明白的话,老师,那怎么才能让我们哈希赛和咱们的判断标准统一呢?也就是说我也希望哈希赛是按咱们的两个属性,如果相同,他们就是同一个对象,你拿内存地址,内存地址我又感受不到,你说拿它来判断的话,我确实不太好理解,我就希望呢,诶,我们的ID和name如果相同,它们就是同一个数据,哎,这个我们能不能做到呢?其实啊,我们如果想让哈希赛和咱们的判断标准统一呢?那么这就需要简单说一说哈希运算的前提了。
04:42
就是说呀,你传递给他一个对象的时候啊,他是如何去做定位操作的,这里咱们给大家解释一下来,咱们找一下我们给他传一个数据的时候,其实他就是用你的哈希code来做的哈希运算,大家想想什么叫哈希code,叫哈希代码啊,我就是通过那个值来做哈希运算,如果你传递一个对象的时候,它就是通过你的哈希code的值来进行哈希定位操作,找到数据应该存放的位置,如果这个位置没有数据,那不用说了,把它直接存进去,比方说这个C,你把这个C呢,给我存进来的时候,这个C的哈希扣就会做运算,运算以后就会存到我的一的位置,为什么呢?因为它得到了一个结果一好了,那这个时候呢,我再存一个什么呢?我的D。
05:23
我如果存D的时候,大家想想,我这个时候也存数据了,但是问题来了,它的这个哈希运算的值有没有可能它也是一呢?这个是完全有可能,对不对?那么如果有可能的情况下,那么这个时候呢,他会判断两个e Co方法它是否相等,如果他发现这两个方法是相等的,就说明是一模一样的数据,那这时候他什么都不会做,直接把它丢弃了就完事了,但是如果他发现,哎,这两个数据啊,它不一样,它不一样,但是又放在同一个小格子里面怎么办?这个时候呢,它会把两个值呢,用链表的结构给它连在一起,所以啊,它的基本逻辑应该是这样的一个逻辑,所以它就形成了一个链表,那么咱们哈希set的底层数据结构呢,它其实是一个数组加链表的这种结构,所以我们回过头来,咱们也去说一下这个事情啊,咱们的哈希啊,Set,它的底层啊,数据结构为我们的数组,再加上我们的链表,诶是这么个意思,好了,为了演示出效果,让我们的这两个对象被我们的。
06:24
哈希塞的集合认为是相同的,我们就需要把我们当前对象的两个方法需要重写一下,一个就叫哈希code,一个就叫ECO4,所以呢,我们这里来,我们快捷键ctrl o ctrl o当中有一个叫哈希code,还有一个叫ES,我们点击OK,那我刚才说过了,这个哈希code呢,可以简单的认为类似于我们的内存地址,所以我们说类似于我们的内存地址行,那我现在干嘛呢?我就把这个ID啊当成我当前的哈希code,难道不行吗?它需要一个int值,我就把ID当成它的int值对不对?那这样的话,我的哈希code的进行哈希定位的时候,它所计算的值,只要你的ID相同,那么我的位置就会计算相同,但是我说了,你的位置相同的情况下,你怎么知道这两个对象是不是同一个对象呢?你并不清楚对不对,所以怎么办?所以呢,我们要用equals来判断一下。
07:15
而这个一的判断也非常简单,就是判断个对象的属性是否相同,所以我们说一下来写上判断啊,我们的两个对象的属性它是否完全相同,如果你完全相同了,我认为是同一个值,所以呢,大家看一下我这个叫equals对不对?好,这个对象是个object,但是你要记住啊,这个对象可不一定是咱们当前的U的对象啊,所以我得判断一下叫做if。括号,然后呢,我写上它,我就判断一下我当前的对象,它是不是我们U9的这个类型的对象,所以我们叫instance of,我们叫U9,如果你这个对象就是我U9这个类型的对象,那不用说了,我可以开始比较了,你如果连这个U9都不是,就没有比较的必要了,所以呢,我这边直接写个else,我们直接return我们的force就可以了。
08:06
诶,那里面我们该怎么做呢?很简单,那你首先我们就写上它,我们就叫U9啊,我们叫U9,然后呢,写上一个叫other u等于我们强制类型转换,为什么可以强制类型转换,因为我已经判断出来了,你当前的对象啊,其实就是我们当前U9的类型吗?那所以我强制类型转换是没有问题的,好,咱们就要判断一下了,我们的两个属性是否相等,首先我们的other啊,咱们的U,它点我们的ID,它等不等于,它等不等于我们当前的this.id就是我当前对象的ID和你传过来的other的ID相不相等,如果相等的情况下,我们if再判断一下咱们的other啊,咱们的U点我们的name,咱们点equals,我们这里啊,不考虑它为空的情况,咱们equals,我们这里的叫this.name就行了。好了,写完了以后,那么如果两个都相等,那么咱们直接写上叫return,我们的true,否则呀,咱们这里呢,否则咱们这里呢,全都给它written force就可以了。同学们能不能明白老师说的意思,我再说一遍,我们首先我要判断一下你当前比较的两个对象是不是相同类型的,你是一个我们的U,它是一个我们的student,你说两个有必要的意义吗?没有,所以必须要保证类型相同,所以我们的这个方法呢,就在判断你当前的对象是不是这个类型,如果你是这个类型的话,好把你强制的转换成这个类型,转换完了以后,要判断你的两个属性是不是相等,如果两个属性是相等的情况下,我认为它俩是相等的,所以返回处只要有一个不相等,我们直接返回false就行了,如果你连这个有点九的类型都不是,那我也直接返回false就可以了,同学们这个逻辑应该还是能明白是吧?好了,如果能明白的情况下,咱们现在就来看一看,我们再去运行运行。
09:58
进行以后看结果,你就会发现我们当前的哈希site里面其实只有一个1001杠三了,这个大家能不能明白,所以啊,这样的话就判断了它的重复,诶老师呀,那如果我当前我改成什么呢?我们叫张三,我写上他叫做我们的王五,我这么写呢,我这么写了以后,同学们记住了一件事情,我们的1001和1001这两个ID是相等的,它俩相等就会让我们当前的数据放在我们的一个小格子里面,对不对?你放到一个小格子里面,但是我们说过了,你得必须两个属性都相等,他会认为是重复数据,但是我们这明显张三和王五不相等吧,所以他就不会认为是重复的,所以它还会保存到我们当前的集合当中,所以我们点击右键运行,运行之后大家看结果,你会发现我们的张三、王五和李四是不是也都会出现啊。
10:48
所以啊,这就是我们所谓的重复性的问题,这个大家能明白吗?
我来说两句