00:00
目前为止,我们已经学习了scla当中的基本语法,基本数据类型,而且了解了它的最重要的两大特性,那就是函数式编程和面向对象编程。接下来的内容呢,我们将要给大家介绍一些比较高级的数据结构和高级的用法。首先我们要介绍的就是集合类型,那集合类型大家也不陌生,很多高级的语言里边都有集合类型的相关定义,像Java当中,集合类型就是有一套完整的类型系统的。我们回顾一下Java啊,Java里边整体来讲集合应该是有三大类。呃,我们应该还记得法当中不要有。List。所谓的列表啊,那另外还有set。所谓的这个数集啊,就是集,然后另外还有一个map,所谓的映射,这是Java当中的三大集合类型啊,那当然大家知道了,一般我们用到的像数组这样的线性数据结构,那对应的应该就是list嘛,List里边有两个非常经典的实现,就是a list和link list,我们一般用它可以对应着去保存成一个数组,那这里边呢,就有一点不太方便的地方啊,就是。
01:22
如果我们在Java里边直接定义一个数组,然后想把它转成list,哎,那一般我们是用什么方法呢?可能需要去调一个Java下边的ar.to list。这样去做一个。做一个改变啊,这样的话才能得到一个list的数据类型啊,所以整体来讲的话是有点奇怪的,大家在学习Java集合的时候可能经常就会搞混淆,诶,这个list到底是什么?那这里的这个A瑞又是什么呢?啊,就经常容易把它们混混为一谈,然后另外Java里边集合类型系统还有一个容易让人引起困惑的地方,那就是Java当中的list和set,它们其实是有一个公共的负接口啊,这三个其实都是Java当中的接口啊,那它们其实都继承自collection。
02:16
Collection我们知道英文里边就是集合的意思嘛,所以它其实看起来就应该是所有集合类型的一个一个根接口,但是map这个类型比较特殊啊,我们知道list和set的区别在于list里边主要是按照顺序排列的一一组数,而set呢,它是没有顺序,但是里边是没有重复数据的这样的一一些数据,所以整体来讲我们都可以把它归在collection里,但是map比较特殊,它是键值,对啊,那对于K,对于键来讲,它是独一无二的,而对于value来讲又是可以重复的,所以看起来它就归不到list和set它们的这一类。所以在Java的实现里边是map和collection它们两者之间其实是完全独立的啊,这是两个完全不同的接口。
03:09
当然了,在map里边我们可以调它的,比方说呃,K set方法啊,Values方法,得到对应的K的集合或者value的集合啊,那这样的话就可以转换成一个的操作了,但是这个我们就看到了,整个类型系统并不统一,而且实现起来中间的转换特别的复杂啊,所以整体来讲,其实Java的集合类型啊,整个类型系统设计的是不够合理的。所以scla既然是基于Java去做改进,那自然要把这个问题解决掉,所以接下来我们看一看SC当中的集合类型是怎么样去定义的,那整体来讲,其实集合的设计跟Java的思路也是类似的,因为我们平常用到的也就那些嘛,所以大家看到集合在scla的集合当中也是三大类型。
04:03
而这里边呢,对应着Java里边的三大类型,List set map,我们看到有两种是一样的,Set和map都保保留了下来,而另外一类呢,Java当中的list这里改成了seek啊,Seek大家知道是sequence英文序列的前三个字母啊,所以相当于是把之前的列表改成了一个序列,那这里大家需要注意的是他们三个。对应的Java里边是接口,那在scda当中呢,那就是treat,就是一个特征,而这所有的三大集合类型的特征都扩展自ter特征啊,所以这就跟Java里边的架构就基本一致了啊,Java里边是呃。List和set继承字collection collection呢,然后又继字啊,那现在我们相当于把这个map就完全都合并在一起了,这是scla当中的整个类型系统的一个整体设计,然后这里需要大家注意的是在SC当中。
05:08
所有的集合类,几乎所有的集合类型KDA当中都提供了两种版本。它同时提供了。可变和不可变两种版本,然后呢,分别位于两个包里边啊,大家注意就是这个可变和不可变呢,不是通过类型系统的继承关系来定义的,而是直接把它放在了不同的包下边啊,所以大家就会想到有一些集合类型,可能它叫同样的名称,但是因为位置不同,就可以表示当前到底是可变的还是不可变的。啊,这后后面我们会给大家做一个具体的介绍,呃,这里面关于所谓的可变不可变,那就是不可变集合呢,指的就是集合对象本身是不可以修改的啊什么意思呢?就是比方说假如我们定义一个。
06:03
呃,定义一个list,当前的一个列表。我们把它如果创建的是一个不可变的列表的话,那就是每一次我们要在这个列表里边增加新的元素的时候,那相当于是。相当于我们要返回的就变成了一个新的历史的对象了,就不能在之前的历史的基础上直接更改,做这个变化啊,那这就有点类似于Java里边的string对吧?大家知道string本来是一个引用类型,我们代表的是一个字符串的对象,但是我并不能在这个string本身的基础上直接改之前的那个对象的值,而是你可以做字符串,字符串拼接得到的就是一个新的string对象啊,这是这样的一个不可变集合的用法,那对应的可变集合呢,那就是可以直接对原来的对象直接做修改,而不会返回新的对象,那就相当于Java里边的string builder啊,那这样。
07:03
这样的一个区分好处在哪里呢?那就是如果说我们当前就希望集合对象不能更改,我相当于我们的原始数据就要放在那儿,然后基于它去做改变得到的新的集合,然后再付给别的值,如果是这样的一种需求的话,那我们干脆就所有的都用不可变集合,这样就会更好。那如果说我们是就希望在。原先原始的集合基础上去做更新去做,呃,删除插入操作的话,相当于我们是原地修改的话,那我们就直接用可变集合就可以了。在后面讲解到这个可变不可变集合类型的操作的时候呢,这里给大家推荐一个基本的小小窍门,一个小用法,就是为了避免大家混淆,可变不可变集合他们能够调用的方法是不一样的,所以推荐大家操作集合的时候,不可变集合用符号来做操作,而可变集合呢,用就英文名称代表的那个方法来做操作啊,当然这个其实说法并不特别的严谨,因为后面前面我们也给大家提到过啊,所谓的运算符,所谓的符号,其实在SKY底层都是一个方法调用啊,只不过就是说看起来它的这个方法的名称是一个符号,比方说一个加号啊,那我们推荐大家对于不可变集合做处理的时候用符号,而可变集合呢,直接调英文名称的方法。
08:34
这就是整体的一个介绍和思路啊,那接下来为了给大家更清楚的知道scla里边的一个类型系统,我们还是把这张图继承图给大家看看一下啊呃,这张图大家看首先看到的是不可变集合的继承图,也就是整个的这个类型系统的关系,我们可以把这张图放大一点。我们看到一上边其实是一个traverseible这样的一个接口类型,呃,当前我们应该叫treat啊特征这样的一个类型,然后它扩展出了一个类啊,就是当扩展出了一个treat叫做terable interable是继承字上面这个traversable这样一个特征的,然后terable呢。
09:20
相当于我们这里边又扩展出了三个。不同的接口,不同的特征,那就是set map和S,就是我们前面说的scla当中的三大集合类型。对应于Java里边呢,诶,那就是set和map基本上是一样的啊,这一点大家稍作区别啊,基本上会看到跟Java里边具体的一些实现也差不多,比方说set,这里我们有哈希set,有tree set啊,当然这里还有bit set啊,还有list set,那map呢,Map我们有哈希map tree map,还有呃list map这里边有一个tree map,大家看到它是sorted map sort map本身也是一个特征,那既然当前这个用数学数结构实现了一个,呃。
10:09
大家看到其实就实现了一个可以排序的功能了,本身map里边是无序的,那如果使用了map,那就是有序的了,这两部分基本上跟Java是一致的,所以我们就不多说了,那最大的区别当然就是下边的sick。它相当于替代的是Java里边的list,那呃,跟list不同的是,我们这里边呢,对于S又做了一个详细的划分,我们看到它主要是分成了两类,一类叫做index seek,另外一个叫linear seek。那整体来讲,英文名称index seek,当然就是说的是带索引的一个序列。啊,那所以我们就知道了,它其实是通过索引位位置来查找当前序列里边的元素,可以快速的定位,所以它的查找速度是很快的啊,比方说我们知道string,那里边我们每一个字符不就都有一个索引位置吗?啊,就我们可以理解成它就是一个数组嘛,呃,大家看这个A瑞也是属于这个index seek的啊,也是一个带索引的序列,所以我们可以通过索引快速定位做查找,这里边有很多对应的这些数据类型啊,啊,当然这里边大家看到有一个我们之前已经见过的。
11:29
Range啊,Range我们说它本身是一个范围在做for循环啊,我们写推导式的时候,最常见的直接写一个,比方说1TO10,它代表的底层其实就是一个R,而R本质上是什么呢?就是一个带索引的序列啊,所以它是一个seek,它是一个集合类型。啊,那对应的还有这个vector,之前我们也见过啊,就是如果我们for循环要想去得到它的一个返回值,我们要生成一个新的集合类型的时候,默认返回的对象类型其实就是vector,而vector它其实也是一一种带索引的序列类型,也是一种seek。
12:13
啊,这是之前我们都已经见过的不同的类型啊,啊,另外还有一个就是数字的范围啊,这大家可以认为是一种特殊的睿,然后另外还有一大类呢,叫做linear seek linear seek,字面上看就是线性的序列啊,所以线性序列的特征其实就是我们并不关心具体的索引,我只知道当前的数据是按照某种顺序依次排列,线性排列就够了啊,那所以在这个线性序列里边,我们最关心的其实是什么呢?在最关心的其实就是一个头,一个尾,所以在这个线性序列里边有head和ta头尾的概念。然后另外呢,就是我们如果想要访问里边的数据,那一般我们想要做的就是要不就是头尾做操作,要不就是直接便利进行一个查找,所以整体来看的话,查找的效率可能不如之前这个带索引的序列更更高效,但是他如果要做一些插入删除删除操作的话,我们往往就直接在头尾那里做就可以了啊,插入删除可能就比这个呃。
13:26
带索引的序列,我们任意插入删除,可能代价就会小一点,比方说我们常见的经典的数据结构。Q,队列和stack站。那大家知道stack是。后进先出,那队列是先进先出,这个就是我们只定义了它这个出和进啊,就是删插入和删除的在头尾的位置啊,所以它其实是一个操作受限的线性表结构,这是大家非常熟悉的一些数据类型。那关于这里的AR瑞和string呢,我们要多说一句,呃,就这里边我们看到它应该是都属于index seek的,就是应该是有扩展了这样一个特征的啊,混入了这样一个特征的,那这里边的array和string呢,跟其他的结构,大家看到这里边蓝色的这个图标表示的就都是具体的集合类型,而这个绿色的图标表示的是treat是特征,那所以这里边呃,AR瑞和string跟其他的具体的集合类型有什么不同呢?我们看到这里边它是虚线指过来的。
14:34
诶,那这个代表的是什么含义呢。结合我们之前讲呃数值类型和引用类型,它整个这个类型系统里边定义的那个实虚线,我们会发现这其实表示的并不是直接的一个继承关系或者扩展关系。我们具体到代码里边可以来参考一下啊,比方说我们随便找一个代码,单立对象里边的main方法啊,我们其实就会传入一个参数AX,这个A本身就是一个AR瑞,就是一个数组嘛,哎,所以我们可以点进去看一下啊,那我们也看过它其实是一个集合类型,那大家如果看这个array本身extend,它继承字或者扩展字哪些哪些特征或者。
15:20
负类或者是这个接口呢,我们看到它直接extend,就是java.io的。Lizable,然后with java.la cable,哎,那大家其实知道这是Java里面的接口嘛,哎,那所以这里边跟SKY的集合类型,我们说所说的这个seek set map3大集合类型一点关系都没有啊。那这到底当前的ARRA到底是怎么定义出来的呢?或者其实大家也知道前面我们讲到的string啊,Skyla当中的string底层不就是。大家看到这个底层不就是Java line下边的string吗?那Java line string显然跟SKY当中的集合类型沾不上边啊,那你怎么能说就是一个index seek是一个索引的序列呢?
16:09
哦,那所以这里大家看到它带的是一个虚线头,虚线,所以它并不是直接有成或者说扩展的关系,而是要通过一些影视转换来做包装,来做转换,然后才能跟skyla里边的集合类型产生关系。好,提到这个包装转换,可能有同学已经想起来了,回忆一下我们之前讲到for循环的时候,For推导式,我们当时给大家解释。在代码里边,这个应该是在第四章。For loop里边,我们当时讲解到这个to的时候,发现它其实是一个方法调用,这个方法调用呢,是在reach in下面有一个to方法,那我们知道在盖拉底层啊,每一个数字,一个整形的数字,整数放过来之后,它其实是一个int类型的对象,那怎么又变成了reach int呢?之前给大家解释过,其实就是在pretty diff这个非常关键的文件里边,我们有很多的影视转换,你给大家,呃,我们来直接搜索一下之前做过的这个影视转换。
17:24
好,我们直接找到这里来,之前我们找到有有一些影视转换,这里边叫做第一优先级的影视转换啊,当时我们就看到了,为什么一个int类型的对象可以直接调rich int下面的方法呢?就是在这里它可以啊,就是如果说我们发现in特里边当前这个编译通不过,它没有to这样一个方法,那我就要找什么呢?编译器就找到了一些影视定义的方法,看它能不能暗暗的啊,偷偷的把这个int类型转换成一个reach int,大家看这里边的t rapper。
18:03
就是这样的一个影视转换的方法,把int转换成了reach int,所以我们说这是把int做了一个包装嘛,Rapper,那对应的下边我们就会看到关于array,关于数组,其实也是有一堆包装的方法的。比方说我们这里边有一个rap int array,它就把一个int类型的数组,一个a int转换成了一个rap a int。所以当前如果说我们直接啊,大家会发现就是这个阿瑞本身它跟斯tda的集合类型没有关系,调不了。SC拉当中,比方说序列对应的那些方法的话,那那怎么办呢?我们这里边可以影视转换成一个rap rarray里边我们就看到了它的继承关系,这是一个抽象类。
19:00
他的继承关系就继承了abstract seek。啊,那当然了,这里边还混入了特征,它的特征是index seek,哎,所以当前我们就说AR瑞Y本身即时是扩展了index seek的方法的,我们知道既然有这样的关系,那当然index seek下边的所有属性和方法在当前的AR里边也就都可以获取到,都可以调用了。这就是这样的一个呃,集合类型的一个过一个转换的过程啊,包括string其实也是类似,我们看到下边对为这个string也有一个rap string的方法,可以把一个string转换成一个raped string,而在这个rap string里边看到它也是继承了abstract with index seek特征。啊,所以整体来看的话,我们这里边就是把所有的集合类型都囊括在了set seek和MAP3大类型里边,即使是就是跟Java要做兼容,我们这里边的array和string两大底层的数据类型,这里边其实通过影视转换也可以把它包含在内。
20:12
整个类型的继承图或者这个树状结构画出来之后非常的完整,非常的清晰,所以这相比Java是一个非常大的改进。然后另外呢,关于。可变集合类型,那么整体来讲跟不可变其实差不多的,这里边呢,就是多了一些。会看到啊,就是多了一些其他的比较特殊的一些集合类型,比方说我们这里边有一些这里有一些接口啊是呃,S synchized map map这里边就相当于是可以做一些同步的处理,对吧,可以加上锁做这个同步处理,那另外在这个seek里边又有一个比较大的变化,我们看到除了index seek和linear seek之外,多出了一个buffer。
21:04
Buffer我们知道有缓冲的意思嘛,所以所谓的buffer缓冲,缓冲池当然就是要不停的添加新的数据过来,然后我们再拿出来用嘛,所以自然它就是一个可变的几何类型。在不可变集合类型里边根本就没有出现可变,这里边多出来一个,所以这里面我们看到之前我们在这个index seek里边不是有array吗。那在这里啊,瑞默认就是。不可变的,那可变的这个叫什么呢?叫做a buffer啊,同样对应的还有string,大家看到这里边是把这个string builder直接就放到这里,属于可变的index seek,它的继承关系,这个就是直接继承了,不再做影视转换。另外呢,大家还有比较熟悉的像list buffer list buffer这个类型,它直接是继承自buffer,它的特征是buffer。啊,另外这里边还有一些stack啊,像这个站对吧,像这个优先队列相关的一些常见的数据类型,在可变集合类型里边,它是直接扩展seek这样一个特征的,就不再去跟这个线性seek啊,跟线性序列去有关系了,所以这里边只是稍微的有一些区别,整体来讲可变不可变,其实整体的结构是完全一致的。
22:27
我们可以看到,确实GALA当中。整个集合类型的定义,它的结构比Java要清晰很多。
我来说两句