一、集合体系
接下来整体学习一下Scala中的集合体系,集合在工作中属于经常使用的数据结构。
首先看一下整个集合体系结构,这个结构与Java的集合体系非常相似。
集合的顶层接口是Iterable,Iterable接口下面还有一些子接口,Set、Seq、Map
这几个子接口下面有具体的实现类。
set下面有HashSet、LinkedHashSet、SortedSet等等
seq下面有List、Buffer、Range等等
Map下面有HashMap、SortedMap、LinkedHashMap等等
其中Buffer下面还有两个常用的,ArrayBuffer、ListBuffer
这是集合中一些常见的实现类
在讲这个集合体系的时候,还会关联讲到Array和Tuple这两个数据结构
二、集合
Scala中的集合是分成可变和不可变两类集合的
其中可变集合就是说,集合的元素可以动态修改
而不可变集合就是说,集合的元素在初始化之后,就无法修改了
可变集合:在scala.collection.mutable这个包下面
不可变集合:在scala.collection.immutable这个包下面
我们在创建集合的时候,如果不指定具体的包名,默认会使用不可变集合
三、Set
先来看一下Set,Set代表一个没有重复元素的集合
这个集合的特性和Java中Set集合的特性基本一样
Set集合分为可变的和不可变的集合,默认情况下使用的是不可变集合
Set可以直接使用,并且不需要使用new关键字,来看一下
这是不是很奇怪,本来Set是一个接口,但是却可以创建对象,更神奇的是竟然还不需要使用new关键字,这就有点颠覆我们的认知了
注意了,大家在学习Scala的时候,可以拿Java来进行对比,加深理解,但是不要全部拿Java里面的知识点来硬套,因为它们两个有些地方还是不一样的。
来看一下Scala的文档,你会发现这个Set不仅仅是一个接口,它还是一个Object,具体这个Object类型我们在后面会详细分析,在这大家先知道这个东西就行了。
注意:本来是应该看对应版本2.12.11的文档的,但是2.12.11文档的格式看起来不是很清晰,所以在这我们就是要2.11.12这个版本了,主要的是没有什么变化的,不影响我们使用
在这大家可以这样理解,只要前面带有object的,可以直接创建对象,并且不需要使用new关键字
所以set可以直接使用。
注意:默认情况下直接创建的set集合是一个不可变集合,在这可以看到是在immutable包里面的,不可变集合中的元素一经初始化,就不能改变了,所以初始化后再向里面添加元素就报错了。
但是注意,我使用s + 4 这种操作是可以的。
这样是不是和我们刚才说的自相矛盾?
不是的,因为 s + 4 返回的是一个新的集合了,相当于在之前的集合的基础上,创建一个新的集合,新的集合包含之前集合的元素和我们新增的4这个元素
这个大家需要能够区分开
如果想要创建一个可变的set集合,可以使用mutable包下面的set集合,显式指定包名
Set常用子类有:HashSet、LinkedHashSet、SortedSet
HashSet:这个集合的特点是:集合中的元素不重复、无序
LinkedHashSet:这个集合的特点是:集合中的元素不重复、有序,它会用一个链表维护插入顺序,可以保证集合中元素是有序的
SortedSet:这个集合的特点是:集合中的元素不重复、有序,它会自动根据元素来进行排序。
演示一下:
1、HashSet
到文档里面看一下
HashSet集合分为可变和不可变之分,immutable包下面的是不可变的,后期无法新增元素。
在这里可以使用new关键字,也可以不使用,因为HashSet既是class,又是object,但是包名需要指定,否则无法识别。
如果在创建集合的时候就初始化了元素,则可以省略泛型的定义,集合会自动识别元素的类型。
2、LinkedHashSet
LinkedHashSet只有可变的,没有不可变的
3、SortedSet
SortedSet分为可变集合和不可变集合
下面的那两个SortedSet是上面collection.SortedSet接口的子接口,一般会使用下面那两个。
从这可以看出来SortedSet集合中的元素是按照元素的字典顺序排序的
针对里面这些Set集合,如果想要迭代他们里面的元素,可以使用for循环直接迭代
以SortedSet为例,其它的Set、HashSet、LinkedHashSet都是一样的
如果还有其它需求的话可以到这里来看一下文档
四、Seq
1、List
接下来看一下List,List属于Seq接口的子接口
List代表一个不可变的列表
注意:为什么有的地方需要写类的全路径,而有的不需要呢?
由于immutable包是默认导入的,所以不需要导包,但是也会有个别虽然在immutable包下面的,但是不写全路径还是报错,原谅它把,反正你都带全路径肯定是没有问题的,后期我们会使用idea来开发,也不需要考虑包名的问题,不过在这为了演示起来更加清晰,就使用scala的命令行了。
针对List有head、tail以及::这几个操作
先演示一下head、tail操作
具体分析一下
head:表示获取List中的第一个元素
tail:表示获取List中第一个元素之后的所有元素
那其实head和tail就可以获取list中的所有元素了
通过::操作符,可以将head和tail的结果合并成一个List
:: 这种操作符要清楚,在spark源码中是有体现的,一定要能够看懂
针对List中的元素进行迭代和前面讲的Set集合的迭代是一样的
2、ListBuffer
在这里List是不可变的列表,在实际工作中使用的时候会很不方便,因为我们很多场景下都是需要向列表中动态添加元素,这个时候该怎么办呢?
Scala还提供的有一个ListBuffer
ListBuffer:可以支持动态增加或者移除元素。
ListBuffer也可以直接使用for循环迭代。
五、Map
Map是一种可迭代的键值对(key/value)结构
Map分为可变和不可变,默认情况下使用的是不可变Map
创建一个不可变的Map
创建一个可变的Map
还有一种创建Map的简易方式,这种方式创建的是不可变Map
1、查询操作
获取指定key对应的value,如果key不存在,会报错
所以在实际工作中这样直接获取不太好,如果遇到了不存在的key程序会报错,导致程序异常退出。
那是不是可以考虑在获取key的值之前,先判断key是否存在
可以使用contains函数检查key是否存在、
使用if-else语句,如果指定的key不存在,则返回一个默认值
这样是没问题的,就是写起来有点麻烦了,有没有方便一点的用法呢?
map中还有一个getOrElse函数。
建议后期从map中获取数据都使用这个getOrElse函数。
2、修改
(1)更新map中的元素
(2)增加多个元素
3、移除元素
4、遍历
(1)遍历map的entrySet
(2)遍历map的key
(3)遍历map的value
5、最后看一下Map的几个子类
HashMap、SortedMap和LinkedHashMap
HashMap:是一个按照key的hash值进行排列存储的map
SortedMap:可以自动对Map中的key进行排序【有序的map】
LinkedHashMap:可以记住插入的key-value的顺序
HashMap分为可变和不可变的,没有什么特殊之处
在这主要演示一下SortedMap和LinkedHashMap
(1)SortedMap
SortedMap是不可变的
(2)LinkedHashMap
LinkedHashMap是可变的
六、Array
Scala中Array的含义与Java中的数组类似,长度不可变。
由于Scala和Java都是运行在JVM中,双方可以互相调用,因此Scala数组的底层实际上就是Java数组。
数组初始化后,长度就固定下来了,而且元素全部根据其类型进行初始化。
也可以直接使用Array()创建数组,元素类型自动推断
七、ArrayBuffer
如果想使用一个长度可变的数组,就需要使用到ArrayBuffer了。
Scala中ArrayBuffer与Java中的ArrayList类似,长度可变。
ArrayBuffer:添加元素、移除元素。
如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类。
1、初始化
使用ArrayBuffer()的方式可以创建一个空的ArrayBuffer。
注意:也支持直接创建并且初始化ArrayBuffer(1,2,3,4)
2、添加元素
使用+=操作符,可以添加一个元素,或者多个元素
b += 1 或者 b += (2, 3, 4, 5)
使用insert()函数可以在指定位置插入元素,但是这种操作效率很低,因为需要移动指定位置后的所有元素。
向3号角标的位置添加一个元素 30
3、移除元素
使用remove()函数可以移除指定位置的元素
移除1号角标的元素
注意:Array与ArrayBuffer可以互相进行转换
b.toArray:ArrayBuffer转Array
a.toBuffer:Array转ArrayBuffer
八、数组常见操作
下面看一下针对数据的常见操作
1、遍历Array和ArrayBuffer的两种方式
由于Array和ArrayBuffer都是有角标的,所以在迭代数组中元素的时候除了可以使用前面迭代集合的方式还可以使用角标迭代
2、求和、求最大值
3、数组排序
九、Tuple
Tuple:称之为元组,它与Array类似,都是不可变的,但与数组不同的是元组可以包含不同类型的元素
Tuple中的元素角标从 1 开始
注意:目前 Scala 支持的元组最大长度为 22 ,对于更大长度可以使用集合或数组
十、总结
前面讲了很多集合体系中的数据结构,有的是可变的,有的是不可变的,有的是既是可变的又是不可变的,听起来有点乱,在这里我们总结一下:
可变集合:LinkedHashSet、ListBuffer、ArrayBuffer、LinkedHashMap
不可变集合:List、SortedMap
可变+不可变集合:Set、HashSet、SortedSet、Map、HashMap
还有两个编外人员:
Array、Tuple
Array:长度不可变,里面的元素可变
Tuple:长度不可变,里面的元素也不可变