00:00
我们看一下下面这个内容,那么直接咱们就不啰嗦了,直接说SC,首先刚才老师讲过,SC呢,它分成不可变和可变,因此首先我们来看一下它这个图,这个图非常的重要。啊,这个图还还还我这样子啊。我我把整个中间来,因为同学们可能有点看不清楚,我放在中间,这样大家看的清晰一点,首先跟着老师。一起来看一下,好,首先我们看上面这个大家看不到啊,最上面这个是什么,我们看一下,最上面是transfer transfer这个呢是最顶级的,我们这个就先不去说它,我们直接看,从这开始看也可以。同学们看到itable这个家伙是所有集合的最上面这一句就是大家都跟什么呢?继承了它。都进行,那么这个it里边分成了三个大类,第一大块set看清楚了,第二大块map看清楚了啊,第三大块sequence。
01:09
Sequence,那么我问同学们一个问题啊,我问同学们一个问题,在你们学这个Java的时候,Set和map是不是都都有提到过,对吧,这个sequence有提到过吗?没有好,所以说这个是它的一个特有的一个玩意儿啊,特有的一个说这个地方呢,它用的还是比较多的。那么呃,而且我们可以看到它在每个这里面,你看这个site里面呢,它也有一个sorted set。啊,它提供排序的功能了,而且大家看到map里面呢,它也提供了一个S的map,也就是说它map呢也可以进行一个排序了,而且我们还可以看到sequence里面呢,分成两大类的序列。注意看啊,序列,序列最大的特点,既然叫序列,是不是它最大的的特点就是有序的呀,哎,这一点大家很清晰,那么它序列呢,又分成两大类,一大类呢,叫做indexed sequence,这个叫,所以序列听其名而知其意,哎,大家知不知道,如果是通过索引序列,那大家知道它的访问的方式,是不是就可以通过我们的下标来走啊,哎,这是它的一个特点,大家看这里,这个地方叫能,呃,能sequence,这个叫线性序列。
02:33
哎,同学们,线性序列最大的特点你们知道是什么吗?就是有头有尾。有头有尾,那么有头有尾的这这东西呢,特在我们的应实际的应用场景用的特别的多,你比如说有头有尾的东西,第一个队列。哎,你看队列就有头有尾,是不是有头,你你排队嘛,第二个站对吧,在你看这里,你看这个哥们,他就直接把我们最像这个应用性比较强的项目。
03:04
这个QQ这个是。队列的意思是不是Q啊,然后s sta,这个大家是是不是这样的意思啊,诶你看他把这种比较应用性比较强的,包括list的stream直接放在了线性序列,因为它有头有尾,也就是说将来大家如果用到一个集合,有头有尾的呢,就可以在这里面去讲learning sequence,如果是索引的,你比如说最经典的叫range,一个范围数组字符串vector,呃,Numeric range,你看这些就是索引,那么一般来讲哈,谁的速度快一点呢?谁的速度快一点,我问大家,一般来讲是不是索引速度要快一点啊,因为我通过下标直接访问到,那么这个线性序列速度呢,理论上说它要慢一点,因为它一般底层是什么时间呢?它一般是用这个链表。链表来实验,当然有些也可能是,嗯,数组加链表形成一个哈希的这么一个结构底层,那么不管怎么样,索引的序列通常要快一些。那么线性序列呢?因为有头有尾,而且它便利的时候,即使你有宿主在里面,也会有一个便利的过程,因此它的速度相对较慢。
04:19
但是它的应用性又特别的强,它的应用性很强,比如说它的应用场景很多,那你说老师你给我举个应用场景呢?来,同学们既然说到这儿了,老师就刚好给他整理了一点小的小好玩的东西。那么以前我在讲Java的时候呢,诶,我在讲Java的时候呢,我一般我在讲数据结构的时候,我会给同学们举几个比较好玩的,比如说程序员玩转算法啊,啊,我到时间把这个也给大家提供一份,以前在大学上学的时候呢,我们也学过这些相应的内容,比如说递归广义表,集合,搜索,链表,排序术语,森林,所以以色列图。
05:04
啊,你们将来就那个那个同学以前做游戏的就知道是吧,数据结构就会用到这些东西啊,你做游戏的他一般就会用到数据结构用的比较多,算法比较多,那么这个呢,到时间我分享一下啊,我们在看一些小好玩的案例,你比如说当时我在讲递归的时候,我就讲了一个这样的玩意儿啊,可能同学们呢,有些有些同学学过地归,就知道有一个特别牛逼的一个项目叫汉洛塔,是不是你们汉洛塔你们学过吗?没没有学过是吧。含含,我就直接给他运行一下啊汉诺塔。我看运行一下是哪一个啊,应该是主函数应该是这hand。Hand。汉诺。汉诺塔,To。好,我看看这个能不能运营起来,诶我我找一下啊,应该是从这个,我找一下主函数在哪里,好久没有用了。
06:04
啊,这个主函数不在这儿。到主函数不在这,在这呢,看一下啊,应该是这个应该是从这儿挪进去的,我D下。第二项加吧。好把这个跑起来。哦,他这个跑不起来,但是难道是从这儿开始的吗?我找一下。To。好,运行起来了,运行起来了,那么这个汉诺塔呢,游戏非常好玩,就是你呢,可以用这个用这些来玩,对吧,你可以这个洞啊移动,然后呢,最后把这边A塔的东西呢,直接运行到C塔,那一般来讲,作为一个人来讲呢,五层我们是可以反应过来的,如果让让你搬80个,我估计一般人搬不动了。80个这个这个塔塔,那么我们来看看代码是怎么玩的呢?你看你看我当时写的一个算法还是很好玩的。
07:06
对吧,你们课后可以自己去想想,如果让你自己来实现这个小小的算法,你自己能不能实现,大概要20多步吧,20步还是30步我忘了。你看这个首先。这个一步一步的往往这边挪动,你看有个来回一个递归的过程。最后呢,AA塔的全部到西塔来看,已经开始要看到这个出行了,你看过来。好,成功了,一共这么多部啊,这是汉洛塔的一个小案例,那当时我们还讲了一个什么呢,诶还讲了一个特别好玩的,就是讲这个队列的时候,我记得特别有意思,当时讲这个队列呢,我讲了一个,为了把这个讲清楚,我讲的这这样一个小案例,我把这个先关掉。就是讲队列,说这个队列的价值在什么地方呢?来写了一个程序啊,当时同学们都学的比较开心啊,然后呢,我写个my bank。
08:03
你看这就是一个,但是很早以前讲的了啊,很早很早以前讲的啊,呃,这是模拟了四个柜台,四个柜台,那么当时的要求呢,就是我这有一堆排队的人,那么每一个柜台呢,会随机的,就是按照顺序从这个排队的这个队列里面找出人为他服务,服务的时间是随机数,你看我这写的。好,我这里有很多排队的。这个其实在这里面就是一个队列,那么队列呢,我这边服务完了过后,就把这个人从这边提出去找到一个对应的柜开为他服务,服务完了过后呢,呃,这个人就离开我们的这个大厅,就是模拟了这么一个流程,其实你们那个叫号啊,叫号就是自动来实现,也可以这么去实现,就是说他这个服务人员做完了过后,他只要按下那个下一个就会自动从这边叫号啊,最后这个系统就把它清空看,最后整个人就走完了。
09:06
你看这个人你消失了,就代表这个人走了,那么整个流程呢,就看到这,诶谁谁谁为谁服务的一个流程全部都出来了,好还是比较好玩的好,那么我在这呢,就举了一下简单的一个应用,那现在呢,我把这个整体的关于时开了不可变集合呢,总结了有这么七句话,那我们来简单看一下哪些地方是需要大家注意的啊来我们简单走一走,这我就不再写了。第一句话,首先我们看到set和map是Java中也有的集合,就说这个用法呢,跟我们Java非常相似。这个准确讲这个可能我们在这学的时候呢,可以几乎可以参照Java,但是它的语法有一点点变化,第二大类sequence是Java没有的,我们发现list就这个家伙,它直接归属到了这个,呃,这个sequence啊,第三个我们前面的for循环的一个1TO3,其实就是indexity sequence下面的vector。
10:08
大家应该回忆我们在学Java的时候,呃,在学那个呃,For循环的时候,我们说可以把for循环的结果直接放到那个VEVE其实就在这出现的,它是一个索引的序列,那么十寸我们发现在哪里?你看这个十寸。你看为什么时针放在这个索引序列的,就是因为首先它是有序的,第二个它可以通过这个索引来访问,大家还记不记得我们在讲这个时针的时候,曾经说过这么一个用法,好,我简单的回忆一下啊,来走一个。DEMO,我直接写这个叫做呃,叫做集合的案例,Connection connection demo01好,同朋友们,我们回忆一下啊,为什么说string也是一个集合呢?啊,其实很好理解,它是这样子的,VR string走。比如说我这有个哈,你看首先它可以被遍历啊,它可以被遍历,每遍历出来一个东西变成什么了呢。
11:08
好,我们可以看到,当我们每遍历出来过后呢,这个item就自动成为char了,这说明在我们的SC里面呢,它的个数组其实就是char字符字符的一个集合啊,从这里我们可以看出来,这字符串字符串在开中。就是什么呢?差的一个集合。而且是一个这样的集合,什么的集合呢?索引的一个sequence,所以说你在变利的时候,顺序一定是按照这个顺序来的,这是第一点,第二点体现出它的索引呢,我们还可以这样来理解,就是是最我直接想访问哪一个,我直接一个小括号,比如说我写个二,写个二的话,那就相当于访问到了这个L啊,这样就打出这个L,我们运行一下,同学们请看运行效果对吧,非常的简单,非常的简单,你看这。
12:00
OK,好,这个我们说到这儿,紧接着我们再来看下面新的特色,往下走。啊,我们发现经典的数据结构,比如像Q和sta,直接被归属到能我这写错了,少了一个,少了一个A。但是少了一个A,把它加进去,少了一个A。Re sequence。那就是线性序列,线性的一个序列,像我们这种经典的数据机构一般是在放到这这边去了。还有第六点,大家注意一下,是看里的map体系的吗?直接支持这个排序了,Short的map,这是SC支持的,呃,Java里面有没有我我有点忘了,好像好像没有吧,啊,我忘了啊,好像是排序要自己去做,但是在我们这个SC里面呢,直接有这种排序的map。再看第七个index sequence和learning sequence的区别在什么地方,刚才已经讲了,而ind sequence通过索引直接查找核定听位,因此它的速度呢相对较快。
13:06
相对较快,比如string就是一个索引集合,通过索引集合定位,那能力尔sequenceence呢,是一个线性的,即有头尾的概念,这种有头尾的概念呢,它一般来说底层通过便利来实现的,当然有有些地方便利它是数组,它一般有些这个为了好做呢,它是做成一个哈希结构的,它是数组加。它数组加链表来实现,因此同学们如果对链表不熟悉的话呢,其实这地方是有一点不好,真不好真正的理解这个哈希的,曾经有同学说说老师,如果我自己想做一个简单的小型的内存哈希结构,我怎么做不知道怎么处理,一般我们都是用现有的结构,比如一般也就是说我用哈希map就可以了,其实哈希map的底层它就是这个数组加列表来实现的,如果我们自己能写一份。
14:01
就特别好,我所以说为什么我推荐大家能够去看一下链表,还是很有用的啊,以前我在工作中,我记得当时有一个场景,我脑海里面还还有印象,什么时候呢,也是我们刚刚参加工作,对吧,跟你们一样,刚刚参加工作的时候呢,啥都不懂,我啥都不懂。但是当时我们这个跟我对接的程序员就提了个要求,提个什么要求呢?他从服务器那边,哦,不是他他是写客户端的,他这个客户端会给我发很多用户的ID,最近他有很多用户ID,比如说好友吗。他比如说因为我做的是一个即时通讯的一个软件,它有很多的ID,这个ID可能是二号,三号,四号,九号,或者是一万零几号,这个ID号呢,它在底层没有排序,因为它排序很困难,在底层。那么他直接把这个ID号发给我了,发给我过后呢,他有一个要求,他有个什么要求呢?他说我把这些ID号给你过后,你要把这些对应的ID的状态发给我。
15:08
而且要把这个各个ID对应的好友也要发给我,但是他有前提,第一个他要求返回的这个用户的ID是顺序排列的。什么意思呢?就是我给你假设我给你的顺序是二三。1103或者是四,一个无序的,但是你返回的是一个有序的字符串。有序的一个字符串,因为我们知道啊,一旦这个数据在网络传输,就没有数据结构的概念了,全是字符串,老师应该讲过。那么这个时候我要有序给他拿回来怎么办呢?而且不能走,不能走数据库啊,不能走数据库,那这个要求还是比较严严格的,那相当于说他给我一个东西,我就要形成一个链表,当时我就用了一个很简单,一个链表就搞定了啊会说诶一号我动态的,我动态的空间这个链表,你首先先先建一个空的链表,来了一个往后面追一个,再追一个点点,再追一个点,那么如果有一个节点在中间,我就把这个人插入到这个链表,把这个叉掉,把这连起来,好我就用用了这么一个结构,就把它的这个问题化解了,诶当时我记得印象很深刻啊,印象很深刻,呃,那个当时我们我们那个头嘛,他是他是那个新任的第一任CTO,他还说,诶这个反正他返回来了,我也不知道怎么返回的,然后他说这个这这处理的还是不错啊,还是表扬了我一下,因为当时我们刚刚参加工作嘛,还是非常希望得到。
16:41
到领导的这个肯定是吧,比如说诶,其实那现在看起来都是不太重要了,当你参刚刚参加工作的时候,其实领导都对你一个表扬,尤其是你特别崇拜的一个人是吧,说诶这小伙子干的挺不错,其实心里面还是很高兴的,对吧,比如说你刚刚参加工作,你说有一个人你你感觉技术很牛,你很服他,他就说诶,这小伙子还是挺挺好的,那心里很高兴啊,当时我中午还多吃了一个馒头啊,还多吃了一个馒头,所以这个呢,就是就是有些东西你看起来在大学里面,我就想在大学里面学的东西,我当时不知道有什么用,确实不知道是有什么用,我觉得这个很无聊,等到你在工作时候突然发现,哦,原来这个东西它还是很有价值的,因此我们古人就有一句话嘛,就是书到用时方恨少,是吧,就你学的时候,你感觉到这没啥用,没啥用,这都没有用,好像都没用。
17:33
等到你工作的时候,你突然发现不会没有用,只是你还没有用到一个东西而已啊,OK,瞎聊了两句,好,那么这个地方我们再说一遍,具体的应用场景在哪里呢?我举一个例子,比如说。比如说哎同学们,比如说我们现在我我鼠标上哪去了,哎,我鼠标呢,诶。我操鼠标丢了。
18:05
鼠标动不了了,卡了吗?诶完了鼠标,诶懂了懂了懂了啊这个鼠标我怖我们来举几个应用场景,你比如说像队列有什么用处呢?或者队列,队列有什么用处呢?最好的用处就这样子的,比如说我现在有个场景啊,就是有个电商网站。电商网站。电商网站你听我说你就知道它有价值了,你们假设你是你是做大数据的,我们就是大数据,大数据呢,人家让你做一个推荐系统,注意听啊,推荐系统,推荐系统,那么假如我有这么一个需求,我要求你生成的这个推荐系统呢,给他返回的这个商品是这个用户。最近浏览的前十个商品,你想这个怎么做啊,推荐系统是要最近啊最近。
19:00
最近浏览的浏览的,呃,十个十个商品。个上品,你想一想,这个时候我们这个队列就很有用了啊对队列,那我就从屁股后面挑四个,或者是这样子的,如果你做一个站的话呢,就从这个占顶调十个就行了,人家因为你们将来这个做的时候一般都不走数据库了,你缺SPA过基本全是在内存里面跑完了过,内存直接做完了过,直接把这个结果就扔给别人。那这个时候你在这个数据结构就显得尤为重要,你不能说诶老师我把这个先写到数据库里面去,然后我排序一把,按照时间排序,黄花菜都凉了。对吧,你说你你在内存里面再排下去,因为你将来是大数据,每个都走数据库,一个用户走下数据库,你10万个人走下数据库,你试试看。你的数据直接就崩了。因为大家知道数据库其实很脆弱的,数据库的这个处理速度跟内存完全不是一个级别,所以你一旦走数据库速度一定会慢,所以你看有经验的程序员,他就非常清晰一点,优化其实就几点,第一点就是说怎么去解决这个对数据库的瓶颈,瓶瓶颈大数据,大流量,大并发,大流量这个问题其实比较好解决。
20:14
那大流量,大流量和大并发,准确的讲比较好解决,为什么这么说呢?你你这个入口,比如说你流量大了,我买带宽嘛。有钱对不对?有钱我买带宽没问题,我只要加带宽就行了,如果再不够大,并发再不够我,我在这个前端,就是外部这一层,我用什么呢?我用负载均衡,我用个集群就解决了,但是最难是在哪里呢?同学们,其实你们后面就知道,其实最难优化的是对数据库这块的并发。就是数据库很脆弱,他没有办法支撑太多的人,你们知道MYSQL默认才多少个吗?MYSQ你们学过吧,默认才100个,那说明他为什么设置100个呢?他说意思就是数据库本身没有我们想的那么强大,一般来讲将来的优化就在数据库,就是你有很多这个查询,啪啪啪啪直接扔给数据数据库,数据库直接卡在这定在这个地方了,所以好多这个好多地方的优化全是针对数据库优化,数据库优化怎么解决呢?一般都用缓存,为什么缓存是一个核心呢?你看现在动不动就说一级缓存,二级缓存,你看为什么Spark Spark这个,它之所以这么流行,Spark这个,Storm这些计算框架为什么流行?因为它整个计算完全不依赖于数据库了,我计算完了结果直接跟给你扔过去了,我不走数据库,一旦走数据库速度就会慢,所以说这个时候我们就会用像类似于像这个q sta所类似的,直接在内存里面计算完毕,直接给他返过去了。
21:42
因为这些数据呢,也没有必要入库,所以说你看当时我举的例例子对吧,如果我就要显示拿十个商品,而且不要走数据库,你直接把它扔到一个队列里面,或者是站里面,对,如果他扔在站里面,我从站里挑上十个就完事了。多简单啊,数据结构你做好了,好,这是一块,还有一块呢,同学们最后再聊两句啊,还有一块就是这一块类体系更加的庞大,这块体系呢,是我们的,可刚才说的是不可变集合,现在是这个是,可我看这是什么,现在是可变集合,同学们可以看到可变集合呢,它也是从这个1RI过来的,它也分成了map set sequence,而且大家可以看到在sequence里面,它又多了另外一个层级是哪里?原先我们不可变只有ex sequence和learning sequence,它这加了一堆buffer,理解什么意思吗?Buffer知道什么吗?缓存缓冲这个地方的用处是特别多的。
22:51
它就可变,在这里面体现出一定机制,你看像瑞瑞buffer这个数组就可变了。就是说在Java里边数组是不可变的,Buffer就可变,这是将来我们用的比较多的,再来一个list buffer。
23:08
前面我们那个list是不可变的,但是我们把我们list肯定会经常用到,往里面加一个呀,减一个这样的东西,好list的buffer就给拿过来了,甚至还有这个synchronized的同步的buffer,看到没有,还有像这个观察者的buffer等等等等。啊,这个就扩展的特别到位,那后面呢,我们都会把这个给大家讲到啊,都给大家讲到,好同学们,那现在呢,我们就把这个可变集合和不可变集合一个整体的一个结构,大家讲完了这两个图我再说一遍,一定要记住。他说老师为什么一定要记住呢?我你不是说的有些东西理解就可以了吗?是理解是很重要的,但是你该记的东西你还要记点,对吧?你学物理,大学学物理,你不初中高中学物理,最重要的牛顿三定律,你说我理解的就行,你还得记住吗?对吧?有些该记的地方还得记一点,说这两个图我是说了啊,你想把这个集合学好,这两个图必须在你脑海里面有一个深刻的印象,你才知道到时候我到底用哪个,我到底是用map呢,还是用sequence,还是用said,它们区别又在哪里?这个图都记不住,你不要说你自己,对吧,学过这个集合啊,你说这个东西很丢份的同学们啊,好,我把这个呢给大家板述一下欧了。
24:30
刚才呢,我花了大量的时间,或者是花了一些时间来把它的体系结构做了一个说明,那显然这个就很重要的。是说这个这个开篇名义的东西其实是特别重要的,来,我给大家简单的板书一把。好,首先再把这个图拿过来啊,这个图就是成绩图啊,图如下,这个图呢,我是要求同学们啊,甚至要求同学们能够背下来。啊,但你不费,那就是你的事儿了。
25:02
对,这个图是非常重要的一个一张图。也不是很难啊,将来你就知道这个图有多重要了,第二个呢,呃,根据刚才的这个说法呢,我做了这么几点小结,那小结呢,根据我自己的一个理解给他做的啊,这个呢,你也在网上找不到啊,因为我们讲课呢,老师我一般会把自己的理解直接融到这里面去。啊,一般书上的他可能就不不总结了,就是把涂医生就救走了。好,然后呢,我把这个简单的给他板出一把,对不对,好。好,这个地方我们说的第三点十寸也是属于这个,好这第五一个对吧?诶第六一个我们发现它的脉谱是可以排序的,然后呢,又说了一下这个indexquence和linear sequence的一个什么区别啊,区别是什么?好啊,这一段我就简单的整理了这么七句话吧啊。那如果将来同学们有这个具体的应用场景,就是如果有具体的应用场景呢,一般来讲你会选择的是这个能力,新词居多啊,居多,当然你还可以扩展啊,你把这个拿到过后呢,我可以做一个扩展,也是有可以的,比如说诶将来我发现有个map普功能不够强,怎么呢,我继承它,然后进行扩展,也是OK的,也是OK的,因为你将来面临的这个需求不知道什么样子,对吧?好,这个第一个我们整理完毕,第二个呢,我们又把这个,呃。
26:32
可变集合的这个预览图给大家整理了下。啊,可变集合的一览图给大家整理一下,那这个呢,我就啊把它写到这里来,写到这里呢,我把这个图也给大家拿过来啊,这个图更加的庞大。啊,这个图体系更加庞大,那这里我单独说一下,就是这这个sequence,它增加一个buffer,这个buffer后面我们用的比较多,就是只要你涉及到像这种可变的,一般会选用or buffer或者是buffer,如果还涉及到这个线程安全的呢,就用sequence的sequence,呃,S的buffer我说一下。
27:10
对对上图的啊,对上图的一个,呃,说明啊说明OK,那现在呢,我这来做一个小小说明。诶,上面这个是图啊,这个是图。OK,那我说明啊,第一点就是第一点在这个可变集合中,在可变集合中对不对,集合集合集合中比这个不可变更加的丰富,比不可变,不可变集合更丰富啊,更加丰富。更加丰富对不对啊呃,体现在哪里呢?就是一个最明显的体现,就是在这里呢,它增加了好多东西,首首先内容肯定增加了,第二个呢,这个buffer是他一个特点。Buffer就是在这个sequence下边,在这个sequence这个集合大类中,这个集合类中,集合这个类中啊,这个这个中啊,增加了,增加了一个叫做buffer的。
28:16
八分的这个类型啊,这个集合啊,集合这里边我们将来用的比较多的啊,将来将来在开发中啊,将来。将来。将来开发中,开发中我们常用常用的有什么呢?A buffer a buffer。和和什么呢?和list buffer好,后面我们在做这个设,呃,设计模式的时候呢,就会用到list buffer,就会用到这个list buffer好,还有一点呢,其他的我就说其他的大体的那这个说啊,还有一个就是如果涉及到啊,如果涉及到。
29:00
如果涉及到涉及到更更强的,就说我我又是可变的,我还要你支持这个线程安全。就说原先那个不可变,它本身是线程安全的,但是不可可变的呢,有时候我还要你涉及到线程安全又怎么办呢?对,如果在这里涉及到这个线程安全。线程安全啊,安全可以选择,可以选择使用以这个sequenceized啊,这个单词啊,就是这个线上安全的这一块是不是。SSYN打头的啊,开头的这个这个集合啊集合。好,那么这个。其他的其他的就跟那个前面一样的啊,其他其他的说明参考参考这个前面说的啊,就是可变集合不可变,集合不可变不可变。
30:02
好好,同学们,这个呢,我就说到这里,截取一段视频。
我来说两句