00:00
大家好,我是海波老师,我们继续来讲Java中的集合list接口啊,咱们已经讲了很多了,那么接下来我们来讲一下set接口,之前提到过set接口呢,它也是我们coll接口的一个子接口,但是和咱们之前所学的那个历史接口啊略有不同,它定义了集合对象中数据是不能重复的,且数据的存储是无序的,那么这里的无序啊,就是你第一个把数据存储进去,但是你第一个取出来的不是它。那么接下来呢,我们就以set接口的实现类哈希set为例,来演示一下我们赛的接口的具体使用,所以啊,我们这里我们来拷贝程序来拷贝,然后呢,把它写成一个九。把这个list呢改成set,点击OK就可以了,那好把这呢我们也给它替换掉。好,Set,然后呢,我们以我们的哈希set为例啊,那么我们首先构建我们的希set,然后set,它等于new咱们的哈希,诶,Set好了,接完了以后大家会发现我们的哈希set它来自于Java YouTube包,我们要用的时候需要把它import进来,没问题吧?嗯,接下来我们通过构造参数来了解一下如何构建这个哈希赛对象,那么首先我们CTRLP提示一下,你会发现我们这里会有很多的构造方法,其中啊会包含了一个初始容量的一个参数,说到这个初始容量的这个参数啊,就很奇怪了,之前啊,咱们讲那个a release的时候说过呀,它的底层组织和管理数据的结构啊,是数组啊,所以我们写上它叫a list,然后呢,它的底层呢是数组,那么数组啊就会有长度的概念,而这里的数组的长度呢,我们就可以称之为叫数组容量。
01:34
所以构造a release对象的时候啊,就会有容量的那个参数,对不对?诶咱们之前还讲过一个什么呢,我们叫link的啊,咱们的list,那么这个link list史啊,它底层组织和管理数据的结构呢,是链表结构,所以啊,构造我们link的历史对象是啊,就没有容量的那个参数了,对不对?诶老师啊,那这里的哈希set的对象构建时也出现了容量的参数,那是不是它的底层也是数组呢?诶不过呀,如果它的底层也是数组的话,那就更奇怪了。
02:03
因为它的底层如果是数组的话,那么我们第一个往里放的数据就会放在我们数组中的第一个,那么你第二个插入的数据就会存放到数组的第二个,这不就有顺序了吗?怎么还会说它是无序的呢?其实啊,说到存储有序的话,咱们之前所学习的那个release集合,它就是这种实现原理,因为啊它的底层是数组,所以a release集合中的数据它存储有序。哎,那要这么说的话,咱们的哈希菜的底层是不是就不是数组呢?因为它没有顺序吗?它是不是采用了其他有容量的结构来组织和管理数据呢?所以为了讲清楚这个问题,我们还是画图来说一下,那么首先呢,我们这里画一个小方框啊,咱们拿过来。好了,画完了以后,把颜色呢,给它变成一个蓝色,跟之前一样,给它写个名称,我们写上它,咱们叫哈西。好了,写完了之后呢,把这个呢,字体呢,稍微的变得醒目一些啊好,接下来我再画一些小方块把它拿过来,那么底层呢,给大家解释一下,我们的哈希赛德的底层啊,它确实它就是数组,所以咱们之前给大家看到的那个容量的参数呢,它就是数组中的长度没问题,所以呢,我们这里简单画一画来。
03:14
我这里呢,给它画上几个小方块儿吧,意思意思啊,来放过来,放过来以后我这里画三个就可以了,意思意思得了啊,然后呢,把它颜色呢,我们给它变成黄色。诶,可以了,画完图以后,大家会发现我们当前的这个哈赛和咱们之前画的那个叫a list非常的类似,但是呢,和咱们的a list呢略有不同,咱们的a release呢,它会将我们的第一个数据呢,给它存放到我们索引零的位置,所以啊,咱把这个呢写成一个零,如果呢,你放的数据呢,是我们的一条数据,OK,比方说我写个A。好了,你把这个A的数据呢,就存放到这里了,把它颜色咱们变一变,诶,这就是我们的A了,那如果你放第二条数据呢,就存放到了我们的什么,我们的一的位置,所以呢,我的第二条数据我们就存放到了我们的这个A,我们写上它,咱们就做B,那么同学们,我们这样的话,取数据的时候,我们就会按照数组的顺序,我们先取我们的第一个就是我们的A,我们再取第二个就是我们的B,那如果再取第三个的话,就可能是C了,对不对,诶,所以我们当时为什么我们的release有序呢?主要原因就是因为它的底层用的是数度。
04:17
但是呢,我们的哈希赛跟它有点不太相同,咱把这个A呀,把这个B呢,我们拿出来啊,把这个C我们也拿出来啊老师,为什么它不相同呢?是因为啊,咱们的名字当中有一个哈希的概念,大家看一下我们的名字当中呢,有一个叫哈希,然后呢,再加上S,哎,老师哈希什么意思?这里呢,给大家解释一啊,我们的哈希呢,它表述的是一个哈希算法来,哈希算法咱们也称之为呢叫散列算法。其实说白了,它就是一个别人封装好的功能,它就像生活中的快递中转站一样,可以将我们的快递啊,根据位置派送到不同的目的地,这个功能呢也是一样的,如果我们给这个哈希算法呀,传递一个值的话,它就会通过计算来返回一个结果,我们根据这个结果就知道我的数据存储到哪去了,所以呢,大家看一下我们这里呢,有个A在我们的哈希set里面,它会有一个哈希算法,所以我写上。
05:13
我们这里写上它,咱们就叫哈希啊,咱们叫做算法就可以了,写完了以后把它拉长一些,诶咱们给它拉长,然后呢,颜色呢,我稍微变一变,嗯,然后呢,加个小图标吧,我这里给他一个小图标啊行了。放过来以后,那么现在呢,这就是我们的哈希算法了,接下来呢,我的A准备往里面放了,我往里面放的时候,记住同学们,我们往里面放并不是直接就往对应的数组的位置去放,而是呢,要通过我的哈希算法来计算,这个计算呀,它可不是说随便计算呢,它有一套逻辑在里面,这个逻辑的计算结果可不能保证你的第一个值,它的计算的索引是零啊,所以呢,它有可能是二啊,就意味着你的A有可能指向了这个位置,所以我的箭头呢,就会指向我当前的二的位置,放到这儿,你放到这以后,我的A呢,其实就走到了这个位置,诶,这就是我们的第一条数据,那好了,那我现在呢,第二条数据B。
06:06
我的这个B的数据呢,我们给它来加上一个绿色,我现在往里面放,记住我们的B往里面放的时候,这个时候呢,我们来拷贝,拷贝以后我们放到这边,你放过来以后,它走同样的哈希计算,但是因为两个值不一样,所以它的结果就可能不是2A可能是一样,所以呢,我们的箭头就指向我们当前的一了,好,你指向一了以后,大家看一下,那我的B不就存到了我的这个位置吗?行了,那我的C是不是就有可能存到了我们的这个位置呀,把颜色呢,咱们也变一下啊,咱们变一下。好了,变一下以后,大家会发现我的三条数据就可能存在了三个不同的小格子当中,那我取数据的时候我该怎么取呢?那我肯定是按照我数组中的顺序取啊,那我第一个要取的肯定是我的零的位置啊,我再取一,我再取二对吗?我这样取的话,大家想想顺序跟我插入的顺序一样吗?那么肯定不一样对不对?所以啊,我们第一个放进去的数据,我第一个不见得取得出来,那这不就是无序的概念吗?这样的话大家能不能体会了呢?
07:07
好了,数据存储的无序的概念呢,咱们就通过画图的方式给大家解释到这里了,那么接下来我们再说一下数据存储不能重复的问题,大家看看啊,我们刚才呢,把我们的数据呢,放了一个A进去,它通过我们的哈希算法定位到了二的位置,好把它去掉。接下来我们准备再往集合里面放一个我们A的数据AOK,把这个A放过来,你要把这个A放过来的话,同学们你要注意了,我们一看,两个不都是A吗?咱们知道它是相等的吧,但是咱们知道,可是哈希赛它不知道吧,所以它会用同样的计算方式,就意味着那么我们的A它还是要通过我们的哈希算法进行定位操作,而问题就在于这个哈希算法的定位操作它不是随机的,它不是说你第一个A过来了以后,我算出了二来了,我第二个A再过来,我算的是一,它不会的,它是幂等性算法。什么叫做幂等性算法呢?简单的理解就是你给这个算法一个固定的值,它在任何情况下计算之后返回的结果一定是一样的,所以也就意味着你给他一个A,你计算二了,你下回再给他A,他计算的还是二。
08:15
那这样的话就会有个问题了,什么呢?你的A呢?它会什么呢?A计算出二的位置,所以它还会指向我当前的这个位置A,这样的话不就冲突了吗?为什么?因为他们俩是相等的呀,那如果要想把这个数据放到集合当中,那么你之前的这个A是不是就会被覆盖掉啊?同学们,没有意义啊,为什么呢?因为两个值一模一样啊,你把之前的值给我去掉了,再放一个相同的值,你图什么呢?对不对?咱们不会这么干吧,既然咱们都不会这么干,那你说哈西菜的他会这么干嘛?所以啊,当数据相同的时候,它不会做任何的处理,为什么呢?一模一样,我做它干嘛呢?所以这个时候A就不用管它了,A给它丢弃掉就完事了。所以啊,咱们总结一下,我们可以往集合中放重复的A,但是它存储的数据它是不会有重复的,懂我的意思吗?同学们,好了啊,这个原理呢,咱们就讲到这里,接下来呢,咱们给大家演示一下它的基本操作,首先我们回来咱们打开,打开以后呢,我们就来写上它,我们写上咱们叫突突啊,我们叫增加数据,增加数据非常简单,咱们的site咱们点,咱们写上它,咱们叫做增加,咱们叫张三,好了,写完了以后,张三,李四,王五,咱们增加三条数据,来我们的李四,然后再写上一个王五,同学们记住了,我们往里面增加了三条数据,但是由于底层的哈希。
09:34
看法的问题,它并不会按照我们的插入顺序来存储,所以咱们打印,打印以后呢,我们写上site,诶,OK,我们运行一下,运行运行之后大家看一下,你会发现我的李四,张三,王五,有没有发现我们这个数据是无序的呀,还有一个我们再来,我们写上李四,我们写上,诶,我们写上两个张三吧。把这个张三呢,我再写一遍,我们放进去两个张三,但是其实它存储的时候是不会存两个张三的,所以我运行一下,运行以后你看结果你会发现他们没有两个,唐山只有一个,对不对,所以啊,放数据可以重复,但是存储数据是不可能重复的,好吧,行了,那增加数据没问题了,那么现在呢,我们修改数据可不可以呢?咱们修改数据我告诉大家不行。
10:17
为什么不行啊,因为咱们修改数据,你首先得先取到它,把它改了吧,对不对?可是你要记住啊,如果想修改数据的话,那么这两个值如果不相等的话,他们的哈希算法计算的值就不一样,这样的话,你就无法保证它能放在我们数组当中的同一个地方吧,你什么叫修改呀?你把这个A我换成C对不对?诶,你要给它换成C,这叫做修改啊,但是你要记住,你这个A和C通过哈希算法,你们定位可能不是一样的吧,那你怎么能保证说你的这个C1定能放到这儿呢?你保证不了啊,所以他就没有所谓的这个修改的方法。哎,老师那怎么办,我想修改怎么办?我们如果想修改的话,就应该是先删除干嘛呀,再增加了,所以我们写上它,我们突do,我们叫做删除啊删除数据好了,我们的site,然后点一下我们叫remove,咱们的remove方法呢,可以把指定的数据删掉,比方说把王五删掉,你把王五删掉的情况下,那么这个时候呢,我们来运行一下,看结果,运行之后大家会发现王五的数据就不会出现了,咱们的李四和张三对不对,哎,就是这个意思。
11:21
诶,老师能增加,能修改,能删除,那么查询行不行啊,所以咱们来说一下咱们嘟do,咱们叫查询数据,其实大家想想也能知道咱们能不能查,查不了,为什么?因为首先你得不到数据的索引,对不对,第二个你怎么知道我们数据,它做过哈希运算以后,它在哪呢?你也不知道,所以呢,我们的site其实是没有对应的这种查询的方式的,你要想查询数据呢,你就只能遍历了,所以咱们写上一个for啊,我们的一个增强for循环,然后呢,我们打印咱们的数据,这个是可以的,把这个数据呢,我放到这边来,然后呢,我们挨个遍历,张三李四王五,把王五删掉,诶这个别删掉了,把它注掉,注掉以后张三李四王五咱们便利之后,我的数据就能出来了,运行。
12:03
运行以后大家看结果没有任何的问题,对不对,所以这里的增加没问题,删除没问题,查询没问题,但是修改会有一些问题啊好了,基本的操作咱们就先演示到这里。
我来说两句