00:00
接下来我们再来介绍一下scla当中三大集合类型的最后一类,那就是map集合。map我们知道有时候翻译会把它翻译成映射,那所谓的map呢?SKY当中跟Java当中的概念是非常类似的,也是一个散列表啊,所以它底层其实就是哈希map这样的一个东西,那它存储的内容是什么呢?就是一对一对的key value,所以整体来讲,Map就是一个键值对k value对的映射集合。那同样了,在SC当中,Map也分为不可变的map以及可变的map,那首先我们要来介绍的就是看看不可变的map到底应该怎么操作,还是在代码里边。当前的包下新建一个scla的object test08,我们现在要测的是不可变的map iutable map那方法首先当然还是要创建map,创建的过程当然就是啊。
01:07
Map肯定是有一个类型神就叫map的,这里边大家需要看一下啊,目前的map在SC当中直接就有定义,如果我们要点进去的话,那在pre Di里边是对当前这个map做了一个相当于重定义的啊,只不过这里是把它定义成一个变量了,那它代表什么呢?就代表以imutable包下边的map,所以这个跟set一样啊,默认直接拿过来它就是不可变,那当前的imutable.map又是个什么呢?诶,这里我们看到它本身首先是可以有一个对象,那我们知道这是伴生对象嘛,另外如果我们直接想要去new它的一个对象行不行呢?不行,跟set一样,它也是一个特征treat。所以接下来我们要定义的最简单的方式,当然就不是去拗它的对象,而是用当前的半生对象。
02:07
传入对应的数据,直接把它创建出来就可以了啊,那这里边传入数据的时候我们就要注意,Map作为一个映射,它里边是包含了key和VALUE2部分的键值,对,那么它跟set或者说list里边的数据当然就是不一样的了,因为set和list里边我们只要保存一同一类的数据,每个元素都是一个数,而现在呢,我们每一个元素保存的元素应该是两个数。一个K,一个value,所以刚才我们也看到了map本身的类型,这里边泛型应该有两个,一个表示当前键的类型,另外一个就是表示当前值的类型,一个k value啊,那接下来如果我们把类型完全完整的写出来的话,目前我们的类型也应该是map,大家看这里边默认要传的话就是nothing nothing啊,那这里边我们定义成。
03:02
比方说最简单的一个思路啊,要保存我们统计的一堆字符串出现的次数,那其实就可以把字符串本身作为一个K,然后呢,把它统计出来的个数,Int类型的数值作为value放到当前的map里面。是对于类型的定义,那我们可以直接定义一个空的map,然后接下来再往里面做操作,我们知道当前这个它应该是不可变的map呀,如果map本身不可变,那我们自然就应该在前边考虑,要往里边直接负出值的时候,给它放一些数值,哎,那当然这个数值应该怎么塞进去呢?之前在Java里面我们都是创建哈希map啊,你有一个哈希map,然后调put方法往里面put。现在有没有更简单的方式呢?就像之前定义set的时候传值这种操作一样。在SC当中是有这种方法的,我们可以看一下要传的是e value显然是一个string类型,比方说A,它对应的value呢,比方说我们统计了它有12个,那我们这里边的符号是用一个连字符加一个大于号,有点像朝右的一个小箭头,哎,这样表示它对应的那个value到底是多少?方说它有13个,那我们就直接一个这样的值就可以了。
04:27
表示保存了一个A13这样的键值,对。啊,那同样我们还可以传多个值,那后面还可以继续给。随便给一个25啊,那后面我们还可以有一个哈,这样一个数据出现了N次,就是我们对于一个不可变集合,不可变map集合做定义的过程啊,那这里我们可以具体的看一下当前MAP1打印出来是什么效果,另外我们也可以看一眼MAP1,刚才我们说过可以直接做一个get class操作,拿到当前的值,它当前类的表达,那接下来我们看一下得到的是什么效果。
05:13
运行下。我们看到当前。Print,呃,Print line map1get class的时候,我们这里边其实拿到的是本身map下边map我们知道是一个特征嘛,呃,然后它有伴生对象,我们调用的其实是它的伴生对象,伴生对象下边的一个一个内部类型,一个子类型叫MAP3,为什么是MAP3呢?因为我们这里边有三个元素嘛,所以相当于它就表示保保存了三个元素的一个具体的map啊,这其实相当于对于我们之前的这个map接口做了一个实现,那那当然里边的这个数据如果我们直接打印的话,可以完整的把它看到,这就是关于创建map的过程,那接下来我们自然就要考虑了,创建出来它要做一些操作,我们怎么样建立前集合当中的元素呢?啊,这个其实非常简单,建立元素我们前。
06:22
边就曾经做过这样的操作,一个最简单的方式可以直接for each啊,当然有同学可能想,那我能不能用for循环,然后去循环便利这里边的东西呢,也是可以的,但是就没有for each这么方便啊,这里边for each,我们这里边直接做一个print,大家知道把printline传进去,就是对于每一个元素和这样的一个打印输出啊,那我们可以看一下当前这个得到的东西是什么。大家看,这就把当前的每一个建职队。包在一个小括号里边,逗号分割,然后做了一个打印输出,A13 B25,哈三,这就是我们当前便利元素直接打印的效果,它的本质其实是做了一个什么操作呢?我们可以把它展开,因为这个是简写之后的效果,如果要是里边写成拉姆的表达式,其实我们当前的参数应该是一个一个k value的值,对。
07:25
当前的这个value建值对它的类型是什么呢?如果我们完整的写出来的类型其实就应该是这样的string in用小括号括起来的的一个类型啊,那这个类型之前我们可能没见过啊,这难道也算是一种数据类型吗?啊,大家可以认为是一种特殊的集合类型,后面我们会讲到这就是所谓的元组。好,然后接下来后边那就是拉姆达表达式的这个箭头的符号LA AV,所以其实我们最终是这样的一个表示。
08:00
那我们用一个分割线分割开。重新做一下测试,看两次打印是不是输出同样的结果,大家看这是完全等效的啊,这就是底层的一个具体的逻辑。呃,那关于前面我们这一个符号,大家一定要做一个区分,因为这里我们用到的KY6之间的连接符是一个单画线加上一个大于号,有点像朝右的一个单箭头。那我们在表示拉姆达表达式,在写匿名函数的时候,或者在表示一个函数类型的时候,中间连接的这一个符号是一个等号加大于号,有点像朝右的一个双箭头。啊,那另外还需要跟之前我们for推导式里边的那个符号要做一个区分,大家还记得for推导式里边我们是一个朝左的单箭头,一个小于号加单画线,所以这个几种不同的符号在加拉当中大家一定要区分开,好,那接下来我们还是解一个分割线。
09:05
那前面我们已经看到了便利map当中的所有元素,那假如说我现在想要访问map当中的某一个元素,或者说我想访问map当中的所有的key,或者想访问map当中的所有value,这样又怎么做呢?诶,这个其实之前在Java里边啊,那那个哈希map里边有对应的这个方法,我们可以直接取它的k set可以取的values啊,那其实在scale当中也是一样的啊,只不过没有key set那么奇怪的一个定义,我们这里边如果要取所有K的话,首先看这个取map中。所有的K或者按钮啊,非常简单,直接一个for循环,我们可以把当前的K啊,这是for推导式的写法,我左的一个箭头方说MAP1当中的我们直接看到有一个方法叫做K,另外有一个方法叫做he set,呃,He set,所以这两个我们都可以直接去调用,Kids得到的是一个interable类型的集合啊,那k set呢,直接得到的就是一个set集合。
10:23
这两种方法都可以,一般情况我们直接调is就可以了,那里边既然是一个集合类型嘛,我们这里边用报推导式直接可以访问集合当中的数据,比方说这里边我们直接print line一下。Other key,然后后边我们可以来一个符号,目前的key是。我们可以直接用。MAP1,哎,那可能想到当前的K啊,我们取出来,但是这个那对应的值又是什么呢?哎,所以接下来我们要取的话,就从MAP1当中到一个方法不就可以了吗?啊,这个跟一般常规的map操作都是一样的啊,所以我们要做代码调用的话,需要把它完整的要在一起,这样的话就实现了我们目前的功能啊,所以整体来讲还是比较简单的啊,我们可以看一下效果怎么样。
11:27
大家看,这就是我们得到的这个东西,A得到了13 B25,哈三,这里大家需要注意的是,诶,这里得到的为什么是一个some呢。啊,这这里我们就发现,如果要是访问访问某一个t value的值的话,我们当然就是直接调用。At方法,而这里边我们直接调用get方法的时候拿到的at,比方说我们这里面直接get a,这里面拿到的是个什么呢?
12:06
这个option类型。的option类型,就是scla当中,为了避免空指针异常,诶这里边如果假如我们获取这个内容有可能为空的话,这个时候把它包成一个option做一个处理,那具体来讲,这个option里面我们也看到了,它也是一个C,呃,Abstract class,这跟我们之前讲的list列表非常的相似,它既然是一个密封的抽象类,那当然就是它具体的实现都在当前这个文件里了,我们直接看到底有哪些实现呢?诶,这里边。最主要的实现就这两个。一个叫做萨。大家看到some就extends option是它的一个实现,Final case class,那另外一个实现就叫,那那大家其实非常熟悉了,它其实就表示里边没有值空值嘛,所以它。
13:00
扩展出来的其实就是option nothing,就是当前如果真的遇到空指针这种状况的话,那我们直接返回的option其实就是一个nu啊,就是一个nu类型,那如果说要是里边有值的话,访问返回的就是一个sum类型,所以大家看这里边我们有值,当然得到就是一个sum了。所以呃,这里我们可以直接get a啊,那有同学可能会想,那假如我就想得到里边具体的这个值,那应该怎么做呢?啊,对于这个some而言,我们看到里边有一个e emptyt方法,看它到底有没有东西,这里面直接就是false了啊,当然不为空了。那另外还有一个方法叫get,那get当然就要返回当前的value。所以如果我们想直接拿到它的值的话,可以大家看到get a之后,然后再找一个方法,哎,这样也是可以得到对应的这个值的,那所以我们可以在这里直接把它打印出来来。
14:03
变形一下。我们会看到直接获得的就是当前A的数值13。啊,那当然了,如果大家要是想拿一个前面我们里边并没有C,有B,但是没有C,那如果要直接打印这个值的话,那应该是什么样的东西呢?我们来运行一下。大家看到输出的就是一个nu啊,就是当前其实你get c get不到嘛,所以应该是一个空指针,哎,但是呢,我们把它包装成了option类型,不会报空指针异常,而是返回一个nu,那自然我们就想到了,那如果要是nu的话,显然这里就不会再有对应的get方法了吧,哎,所以大家看,如果要是你调这个get方法,它直接会抛一个异常出来,No such element exception,那这里边我怎么样能避免出现这种情况呢?我怎么知道这里边get c之后调钙的方法,它会不会抛异常呢?
15:04
你像前面这个A,我们直接就在后面直接调get了,那假如抛异常的这种情况,我们其实在代码里边编译的时候是根本不知道的,只有运行了之后才知道到底有没有这个T啊,所以我们也看到这里边有一个警告的提示啊,这种写法其实是不够安全的,所以这里边其实最好的写法是什么呢?Print line,第一这里我们可以直接给一个上面有at all。Else直接用这样的一个方式,所以如果我们用了get else的话,它表示的含义其实就是我们去获取当前Z的值,如果要是没有值的话,我就直接返回一个默认的故值值啊,所以这里我们可以直接把这个一个叠加。
16:01
突出一下当前的值,这样下边这里边我们可以把C的值做一个打印。变形下,你看现在的效果怎么样?我们会看到第一个输出的当然是A,是13,但是其实这里面我们并没有做额外的判断,假如它是那样的话,那这里就直接抛一成了。而下面。这个C直接get之后得到的是,那这里我们就不能直接调get,如果直接这里调get的话,这个大家能想到中间就会直接抛出一个异常,没有这个值,那所以我们对应的呢,做了一个else,如果发现没有的时候的时候,直接返回零就可以了,这个在很多代码里边其实是非常常见的一个编程小技巧,在JAVA8当中引入了一个新特性叫做optional,其实也是借鉴了skyla当中的这个option类型,所以这里边大家可以做一个具体的了解。
我来说两句