第 7 章 集 合

7.1 集合简介

  • Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable 特质。

  • 对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两 个包

    • 不可变集合:scala.collection.immutable
    • 可变集合: scala.collection.mutable
  • Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而 不会对原对象进行修改。类似于 java 中的 String 对象

  • 可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似 于 java 中 StringBuilder 对象

建议:在操作集合的时候,不可变用符号,可变用方法

7.1.1 不可变集合继承图

image-20210405214331772

1)Set、Map 是 Java 中也有的集合

2)Seq 是 Java 没有的,我们发现 List 归属到 Seq 了,因此这里的 List 就和 Java 不是同一个 概念了

3)我们前面的 for 循环有一个 1 to 3,就是 IndexedSeq 下的 Range

4)String 也是属于 IndexedSeq

5)我们发现经典的数据结构比如 Queue 和 Stack 被归属到 LinearSeq(线性序列)

6)大家注意 Scala 中的 Map 体系有一个 SortedMap,说明 Scala 的 Map 可以支持排序

7)IndexedSeq 和 LinearSeq 的区别:

  • IndexedSeq 是通过索引来查找和定位,因此速度快,比如 String 就是一个索引集合,通过索引即可定位
  • LinearSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

7.1.2 可变集合继承图

image-20210405214500338

7.2 数组

7.2.1 不可变数组

1)第一种方式定义数组

定义:val arr1 = new Array[Int](10)

(1)new 是关键字

(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定 Any

(3)(10),表示数组的大小,确定后就不可以变化

2)第二种方式定义数组

定义: val arr1 = Array(1, 2)

(1)在定义数组时,直接赋初始值

(2)使用 apply 方法创建数组对象

3)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
object Test01_ImmutableArray {
def main(args: Array[String]): Unit = {
// 1. 创建数组
val arr: Array[Int] = new Array[Int](5)
// 另一种创建方式
val arr2 = Array(12, 37, 42, 58, 97)
println(arr)

// 2. 访问元素
println(arr(0))
println(arr(1))
println(arr(4))
// println(arr(5)) 下标越界

arr(0) = 12
arr(4) = 57
println(arr(0))
println(arr(1))
println(arr(4))

println("========================")

// 3. 数组的遍历
// 1) 普通for循环
for (i <- 0 until arr.length){
println(arr(i))
}

for (i <- arr.indices) println(arr(i))

println("---------------------")

// 2) 直接遍历所有元素,增强for循环
for (elem <- arr2) println(elem)

println("---------------------")

// 3) 迭代器
val iter = arr2.iterator

while (iter.hasNext)
println(iter.next())

println("---------------------")

// 4) 调用foreach方法
arr2.foreach( (elem: Int) => println(elem) )

arr.foreach( println )

println(arr2.mkString("--"))

println("========================")
// 4. 添加元素
val newArr = arr2.:+(73)
println(arr2.mkString("--"))
println(newArr.mkString("--"))

val newArr2 = newArr.+:(30) // .+:为插入到前面
println(newArr2.mkString("--"))

val newArr3 = newArr2 :+ 15
val newArr4 = 19 +: 29 +: newArr3 :+ 26 :+ 73
println(newArr4.mkString(", "))
}
}

[I@4563e9ab
0
0
0
12
0
57
========================
12
0
0
0
57
12
0
0
0
57
---------------------
12
37
42
58
97
---------------------
12
37
42
58
97
---------------------
12
37
42
58
97
12
0
0
0
57
12--37--42--58--97
========================
12--37--42--58--97
12--37--42--58--97--73
30--12--37--42--58--97--73
19, 29, 30, 12, 37, 42, 58, 97, 73, 15, 26, 73

7.2.2 可变数组

1)定义变长数组

val arr01 = ArrayBuffer[Any](3, 2, 5)

(1)[Any]存放任意数据类型

(2)(3, 2, 5)初始化好的三个元素

(3)ArrayBuffer 需要引入 scala.collection.mutable.ArrayBuffer

2)案例实操

(1)ArrayBuffer 是有序的集合

(2)增加元素使用的是 append 方法(),支持可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
object Test02_ArrayBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变数组
val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
val arr2 = ArrayBuffer(23, 57, 92)

println(arr1)
println(arr2)

// 2. 访问元素
// println(arr1(0)) // error
println(arr2(1))
arr2(1) = 39
println(arr2(1))

println("======================")
// 3. 添加元素
val newArr1 = arr1 :+ 15
println(arr1)
println(newArr1)
println(arr1 == newArr1) // false

val newArr2 = arr1 += 19
println(arr1)
println(newArr2)
println(arr1 == newArr2) // true
newArr2 += 13
println(arr1) // 19 13

77 +=: arr1
println(arr1) // 77 19 13
println(newArr2) // 77 19 13

arr1.append(36)
arr1.prepend(11, 76) //数组头部插入 11 76
arr1.insert(1, 13, 59) // 索引为1的地方 插入 13 59
println(arr1)

arr1.insertAll(2, newArr1) // 索引为2位置插入 一个数组
arr1.prependAll(newArr2)// 头部插入 一个数组

println(arr1)

// 4. 删除元素
arr1.remove(3)
println(arr1)

arr1.remove(0, 10)
println(arr1)

arr1 -= 13
println(arr1)

}
}

image-20210405215555124

7.2.3 不可变数组与可变数组的转换

1)说明

arr1.toBuffer //不可变数组转可变数组

arr2.toArray //可变数组转不可变数组

  • arr2.toArray 返回结果才是一个不可变数组,arr2 本身没有变化

  • arr1.toBuffer 返回结果才是一个可变数组,arr1 本身没有变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
object Test02_ArrayBuffer {
def main(args: Array[String]): Unit = {


// 5. 可变数组转换为不可变数组
val arr: ArrayBuffer[Int] = ArrayBuffer(23, 56, 98)
val newArr: Array[Int] = arr.toArray
println(newArr.mkString(", "))
println(arr)

// 6. 不可变数组转换为可变数组
val buffer: mutable.Buffer[Int] = newArr.toBuffer
println(buffer)
println(newArr)
}
}

image-20210405215645151

7.2.4 多维数组

1)多维数组定义

1
val arr = Array.ofDim[Double](3,4) 

说明:二维数组中有三个一维数组,每个一维数组中有四个元素

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
object Test03_MulArray {
def main(args: Array[String]): Unit = {
// 1. 创建二维数组
val array: Array[Array[Int]] = Array.ofDim[Int](2, 3)

// 2. 访问元素
array(0)(2) = 19
array(1)(0) = 25

println(array.mkString(", "))
for (i <- 0 until array.length; j <- 0 until array(i).length){
println(array(i)(j))
}
for (i <- array.indices; j <- array(i).indices){
print(array(i)(j) + "\t")
if (j == array(i).length - 1) println()
}

array.foreach(line => line.foreach(println))

array.foreach(_.foreach(println))
}
}

7.3 列表 List

7.3.1 不可变 List

1)说明

(1)List 默认为不可变集合

(2)创建一个 List(数据有顺序,可重复)

(3)遍历 List

(4)List 增加数据

(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化

(6)取指定数据

(7)空集合 Nil

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
object Test04_List {
def main(args: Array[String]): Unit = {
// 1. 创建一个List
val list1 = List(23, 65, 87)
println(list1)

// 2. 访问和遍历元素
println(list1(1))
// list1(1) = 12
list1.foreach(println)

// 3. 添加元素
val list2 = 10 +: list1
val list3 = list1 :+ 23
println(list1)
println(list2)
println(list3)

println("==================")

val list4 = list2.::(51)
println(list4)

val list5 = Nil.::(13)
println(list5)

val list6 = 73 :: 32 :: Nil
val list7 = 17 :: 28 :: 59 :: 16 :: Nil
println(list7)
println("==================")
// 4. 合并列表
val list8 = list6 :: list7
println(list8)

val list9 = list6 ::: list7
println(list9)

val list10 = list6 ++ list7
println(list10)

}
}

image-20210405222437855

7.3.2 可变 ListBuffer

1)说明

(1)创建一个可变集合 ListBuffer

(2)向集合中添加数据

(3)打印集合数据

2) 案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
object Test05_ListBuffer {
def main(args: Array[String]): Unit = {
// 1. 创建可变列表
val list1: ListBuffer[Int] = new ListBuffer[Int]()
val list2 = ListBuffer(12, 53, 75)

println(list1)
println(list2)

println("==============")

// 2. 添加元素
list1.append(15, 62)
list2.prepend(20)

list1.insert(1, 19, 22)

println(list1)
println(list2)

println("==============")

31 +=: 96 +=: list1 += 25 += 11
println(list1)

println("==============")
// 3. 合并list
val list3 = list1 ++ list2
println(list1)
println(list2)

println("==============")

list1 ++=: list2
println(list1)
println(list2)

println("==============")

// 4. 修改元素
list2(3) = 30
list2.update(0, 89)
println(list2)

// 5. 删除元素
list2.remove(2)
list2 -= 25
println(list2)
}
}

image-20210405222830658

7.4 Set 集合

默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包

7.4.1 不可变 Set

1)说明

(1)Set 默认是不可变集合,数据无序

(2)数据不可重复

(3)遍历集合

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
object Test06_ImmutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建set
val set1 = Set(13, 23, 53, 12, 13, 23, 78)
println(set1)

println("==================")

// 2. 添加元素
val set2 = set1 + 129
println(set1)
println(set2)
println("==================")

// 3. 合并set
val set3 = Set(19, 13, 23, 53, 67, 99)
val set4 = set2 ++ set3
println(set2)
println(set3)
println(set4)

// 4. 删除元素
val set5 = set3 - 13
println(set3)
println(set5)
}
}

image-20210405223209761

7.4.2 可变 mutable.Set

1)说明

(1)创建可变集合 mutable.Set

(2)打印集合

(3)集合添加元素

(4)向集合中添加元素,返回一个新的 Set

(5)删除数据

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
object Test07_MutableSet {
def main(args: Array[String]): Unit = {
// 1. 创建set
val set1: mutable.Set[Int] = mutable.Set(13, 23, 53, 12, 13, 23, 78)
println(set1)

println("========2. 添加元素==========")

// 2. 添加元素
val set2 = set1 + 11
println(set1)
println(set2)

set1 += 11
println(set1)

val flag1 = set1.add(10)
println(flag1)
println(set1)
val flag2 = set1.add(10)
println(flag2)
println(set1)

println("========3. 删除元素==========")

// 3. 删除元素
set1 -= 11
println(set1)

val flag3 = set1.remove(10)
println(flag3)
println(set1)
val flag4 = set1.remove(10)
println(flag4)
println(set1)

println("========4. 合并两个Set==========")

// 4. 合并两个Set
val set3 =mutable.Set(13,12,13,27,98,29)
println(set1)
println(set3)
println("==================")
val set4 = set1 ++ set3
println(set1)
println(set3)
println(set4)
}
}

image-20210405223633098

7.5 Map

集合 Scala 中的 Map 和 Java 类似,也是一个散列表,它存储的内容也是键值对(key-value) 映射

7.5.1 不可变 Map

1)说明

(1)创建不可变集合 Map

(2)循环打印

(3)访问数据

(4)如果 key 不存在,返回 0

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
object Test08_ImmutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1: Map[String, Int] = Map("a" -> 13, "b" -> 25, "hello" -> 3)
println(map1)
println(map1.getClass)

println("==========================")
// 2. 遍历元素
map1.foreach(println)
map1.foreach( (kv: (String, Int)) => println(kv) )

println("============================")

// 3. 取map中所有的key 或者 value
for (key <- map1.keys){
println(s"$key ---> ${map1.get(key)}")
}

// 4. 访问某一个key的value
println("a: " + map1.get("a").get)
println("c: " + map1.get("c"))
println("c: " + map1.getOrElse("c", 0))

println(map1("a"))
}
}

image-20210405224340476

7.5.2 可变 Map

1)说明

(1)创建可变集合

(2)打印集合

(3)向集合增加数据

(4)删除数据

(5)修改数据

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
object Test09_MutableMap {
def main(args: Array[String]): Unit = {
// 1. 创建map
val map1: mutable.Map[String, Int] = mutable.Map("a" -> 13, "b" -> 25, "hello" -> 3)
println(map1)
println(map1.getClass)

println("========2. 添加元素==================")

// 2. 添加元素
map1.put("c", 5)
map1.put("d", 9)
println(map1)

map1 += (("e", 7))
println(map1)

println("=======3. 删除元素=============")

// 3. 删除元素
println(map1("c"))
map1.remove("c")
println(map1.getOrElse("c", 0))

map1 -= "d"
println(map1)

println("========4. 修改元素============")

// 4. 修改元素
map1.update("c", 5)
map1.update("e", 10)
println(map1)

println("========5. 合并两个Map============")

// 5. 合并两个Map
val map2: Map[String, Int] = Map("aaa" -> 11, "b" -> 29, "hello" -> 5)
// map1 ++= map2
println(map1)
println(map2)

println("---------------------------")
val map3: Map[String, Int] = map2 ++ map1
println(map1)
println(map2)
println(map3)
}
}

image-20210405224632115

7.6 元组

1)说明

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。

注意:元组中最大只能有 22 个元素。

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
object Test10_Tuple {
def main(args: Array[String]): Unit = {
// 1. 创建元组
val tuple: (String, Int, Char, Boolean) = ("hello", 100, 'a', true)
println(tuple)

// 2. 访问数据
println(tuple._1)
println(tuple._2)
println(tuple._3)
println(tuple._4)

println(tuple.productElement(1))

println("====================")
// 3. 遍历元组数据
for (elem <- tuple.productIterator)
println(elem)

// 4. 嵌套元组
val mulTuple = (12, 0.3, "hello", (23, "scala"), 29)
println(mulTuple._4._2)
}
}

image-20210405224831124

7.7 集合常用函数

7.7.1 基本属性和常用操作

1)说明

(1)获取集合长度

(2)获取集合大小

(3)循环遍历

(4)迭代器

(5)生成字符串

(6)是否包含

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
object Test11_CommonOp {
def main(args: Array[String]): Unit = {
val list = List(1,3,5,7,2,89)
val set = Set(23,34,423,75)

// (1)获取集合长度
println(list.length)

// (2)获取集合大小
println(set.size)

// (3)循环遍历
for (elem <- list)
println(elem)

set.foreach(println)

// (4)迭代器
for (elem <- list.iterator) println(elem)

println("====================")
// (5)生成字符串
println(list)
println(set)
println(list.mkString("--"))

// (6)是否包含
println(list.contains(23))
println(set.contains(23))
}
}

image-20210405225126258

7.7.2 衍生集合

1)说明

(1)获取集合的头

(2)获取集合的尾(不是头的就是尾)

(3)集合最后一个数据

(4)集合初始数据(不包含最后一个)

(5)反转 (6)取前(后)n 个元素

(7)去掉前(后)n 个元素

(8)并集

(9)交集

(10)差集

(11)拉链

(12)滑窗

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
object Test12_DerivedCollection {
def main(args: Array[String]): Unit = {
val list1 = List(1,3,5,7,2,89)
val list2 = List(3,7,2,45,4,8,19)

// (1)获取集合的头
println(list1.head)

// (2)获取集合的尾(不是头的就是尾)
println(list1.tail)

// (3)集合最后一个数据
println(list2.last)

// (4)集合初始数据(不包含最后一个)
println(list2.init)

// (5)反转
println(list1.reverse)

// (6)取前(后)n个元素
println(list1.take(3))
println(list1.takeRight(4))

// (7)去掉前(后)n个元素
println(list1.drop(3))
println(list1.dropRight(4))

println("========(8)并集=================")
// (8)并集
val union = list1.union(list2)
println("union: " + union)
println(list1 ::: list2)

// 如果是set做并集,会去重
val set1 = Set(1,3,5,7,2,89)
val set2 = Set(3,7,2,45,4,8,19)

val union2 = set1.union(set2)
println("union2: " + union2)
println(set1 ++ set2)

println("--------(9)交集---------------")
// (9)交集
val intersection = list1.intersect(list2)
println("intersection: " + intersection)

println("---------(10)差集--------------")
// (10)差集
val diff1 = list1.diff(list2)
val diff2 = list2.diff(list1)
println("diff1: " + diff1)
println("diff2: " + diff2)

println("---------(11)拉链--------------")
// (11)拉链
println("zip: " + list1.zip(list2))
println("zip: " + list2.zip(list1))

println("----------(12)滑窗-------------")
// (12)滑窗
for (elem <- list1.sliding(3))
println(elem)
println("-----------------------")

for (elem <- list2.sliding(4, 2))
println(elem)

println("-----------------------")
for (elem <- list2.sliding(3, 3))
println(elem)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1
List(3, 5, 7, 2, 89)
19
List(3, 7, 2, 45, 4, 8)
List(89, 2, 7, 5, 3, 1)
List(1, 3, 5)
List(5, 7, 2, 89)
List(7, 2, 89)
List(1, 3)
========(8)并集=================
union: List(1, 3, 5, 7, 2, 89, 3, 7, 2, 45, 4, 8, 19)
List(1, 3, 5, 7, 2, 89, 3, 7, 2, 45, 4, 8, 19)
union2: Set(5, 89, 1, 2, 45, 7, 3, 8, 19, 4)
Set(5, 89, 1, 2, 45, 7, 3, 8, 19, 4)
--------(9)交集---------------
intersection: List(3, 7, 2)
---------(10)差集--------------
diff1: List(1, 5, 89)
diff2: List(45, 4, 8, 19)
---------(11)拉链--------------
zip: List((1,3), (3,7), (5,2), (7,45), (2,4), (89,8))
zip: List((3,1), (7,3), (2,5), (45,7), (4,2), (8,89))
----------(12)滑窗-------------
List(1, 3, 5)
List(3, 5, 7)
List(5, 7, 2)
List(7, 2, 89)
-----------------------
List(3, 7, 2, 45)
List(2, 45, 4, 8)
List(4, 8, 19)
-----------------------
List(3, 7, 2)
List(45, 4, 8)
List(19)

7.7.3 集合计算简单函数

1)说明

(1)求和

(2)求乘积

(3)最大值

(4)最小值

(5)排序

2)代码实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
object Test13_SimpleFunction {
def main(args: Array[String]): Unit = {
val list = List(5,1,8,2,-3,4)
val list2 = List(("a", 5), ("b", 1), ("c", 8), ("d", 2), ("e", -3), ("f", 4))

// (1)求和
var sum = 0
for (elem <- list){
sum += elem
}
println(sum)

println(list.sum)

// (2)求乘积
println(list.product)

// (3)最大值
println(list.max)
println(list2.maxBy( (tuple: (String, Int)) => tuple._2 ))
println(list2.maxBy( _._2 ))

// (4)最小值
println(list.min)
println(list2.minBy(_._2))

println("========================")

// (5)排序
// 5.1 sorted
val sortedList = list.sorted
println(sortedList)

// 从大到小逆序排序
println(list.sorted.reverse)
// 传入隐式参数
println(list.sorted(Ordering[Int].reverse))

println(list2.sorted)

// 5.2 sortBy
println(list2.sortBy(_._2))
println(list2.sortBy(_._2)(Ordering[Int].reverse))

// 5.3 sortWith
println(list.sortWith( (a: Int, b: Int) => {a < b} ))
println(list.sortWith( _ < _ ))
println(list.sortWith( _ > _))
}
}

image-20210405225658412

(1)sorted 对一个集合进行自然排序,通过传递隐式的 Ordering

(2)sortBy 对一个属性或多个属性进行排序,通过它的类型。

(3)sortWith 基于函数的排序,通过一个 comparator 函数,实现自定义排序的逻辑。

7.7.4 集合计算高级函数

1)说明

  • 过滤

    • 遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
  • 转化/映射(map)

    • 将集合中的每一个元素映射到某一个函数
  • 扁平化

  • 扁平化+映射

    • 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作 集合中的每个元素的子元素映射到某个函数并返回新集合
  • 分组(group)

    • 按照指定的规则对集合的元素进行分组
  • 简化(归约)

  • 折叠

2)集合转换操作(Map类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
object Test14_HighLevelFunction_Map {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5,6,7,8,9)
println("==========1. 过滤=============")
// 1. 过滤
// 选取偶数
val evenList = list.filter( (elem: Int) => {elem % 2 == 0} )
println(evenList)

// 选取奇数
println(list.filter( _ % 2 == 1 ))

println("==========把集合中每个数乘2=============")

// 2. 映射map
// 把集合中每个数乘2
println(list.map(_ * 2))
println(list.map( x => x * x))

println("=========== // 3. 扁平化============")

// 3. 扁平化
val nestedList: List[List[Int]] = List(List(1,2,3),List(4,5),List(6,7,8,9))

val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
println(flatList)

val flatList2 = nestedList.flatten
println(flatList2)

println("========/ 4. 扁平映射===============")

// 4. 扁平映射
// 将一组字符串进行分词,并保存成单词的列表
val strings: List[String] = List("hello world", "hello scala", "hello java", "we study")
val splitList: List[Array[String]] = strings.map( _.split(" ") ) // 分词

println(splitList)
val flattenList = splitList.flatten // 打散扁平化

println(flattenList)

val flatmapList = strings.flatMap(_.split(" "))
println(flatmapList)

println("===========// 5. 分组groupBy=============")

// 5. 分组groupBy
// 分成奇偶两组
val groupMap: Map[Int, List[Int]] = list.groupBy( _ % 2)
val groupMap2: Map[String, List[Int]] = list.groupBy( data => if (data % 2 == 0) "偶数" else "奇数")

println(groupMap)
println(groupMap2)

// 给定一组词汇,按照单词的首字母进行分组
val wordList = List("china", "america", "alice", "canada", "cary", "bob", "japan")
println( wordList.groupBy( _.charAt(0) ) )
}
}

image-20210405230155439

3)集合转换操作(Reduce类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
object Test15_HighLevelFunction_Reduce {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)

// 1. reduce
println(list.reduce( _ + _ ))
println(list.reduceLeft(_ + _))
println(list.reduceRight(_ + _))

println("===========================")

val list2 = List(3,4,5,8,10)
println(list2.reduce(_ - _)) // -24
println(list2.reduceLeft(_ - _))
println(list2.reduceRight(_ - _)) // 3 - (4 - (5 - (8 - 10))), 6

println("===========================")
// 2. fold
println(list.fold(10)(_ + _)) // 10 + 1 + 2 + 3 + 4
println(list.foldLeft(10)(_ - _)) // 10 - 1 - 2 - 3 - 4
println(list2.foldRight(11)(_ - _)) // 3 - (4 - (5 - (8 - (10 - 11)))), -5
}
}

image-20210405230343556

4)Fold 方法

Fold 折叠:化简的一种特殊情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
object Test16_MergeMap {
def main(args: Array[String]): Unit = {
val map1 = Map("a" -> 1, "b" -> 3, "c" -> 6)
val map2 = mutable.Map("a" -> 6, "b" -> 2, "c" -> 9, "d" -> 3)

//这种方式得到的重复元组会覆盖 现在需求是加起来
// println(map1 ++ map2)

val map3 = map1.foldLeft(map2)(
(mergedMap, kv) => {
val key = kv._1
val value = kv._2
mergedMap(key) = mergedMap.getOrElse(key, 0) + value
mergedMap
}
)

println(map3)
}
}

image-20210405230623566

7.7.5 普通 WordCount 案例

1)需求

单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果

2)需求分析

image-20210405230758002

3)代码实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
object Test17_CommonWordCount {
def main(args: Array[String]): Unit = {
val stringList: List[String] = List(
"hello",
"hello world",
"hello scala",
"hello spark from scala",
"hello flink from scala"
)

// 1. 对字符串进行切分,得到一个打散所有单词的列表
// val wordList1: List[Array[String]] = stringList.map(_.split(" "))
// val wordList2: List[String] = wordList1.flatten
// println(wordList2)
val wordList = stringList.flatMap(_.split(" "))
println(wordList)

// 2. 相同的单词进行分组
val groupMap: Map[String, List[String]] = wordList.groupBy(word => word)
println(groupMap)

// 3. 对分组之后的list取长度,得到每个单词的个数
val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))

// 4. 将map转换为list,并排序取前3
val sortList: List[(String, Int)] = countMap.toList
.sortWith( _._2 > _._2 )
.take(3)

println(sortList)
}
}

image-20210405230916428

7.7.6 复杂 WordCount 案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
object Test18_ComplexWordCount {
def main(args: Array[String]): Unit = {
val tupleList: List[(String, Int)] = List(
("hello", 1),
("hello world", 2),
("hello scala", 3),
("hello spark from scala", 1),
("hello flink from scala", 2)
)

// 思路一:直接展开为普通版本
val newStringList: List[String] = tupleList.map(
kv => {
(kv._1.trim + " ") * kv._2
}
)
println(newStringList)

// 接下来操作与普通版本完全一致
val wordCountList: List[(String, Int)] = newStringList
.flatMap(_.split(" ")) // 空格分词
.groupBy( word => word ) // 按照单词分组
.map( kv => (kv._1, kv._2.size) ) // 统计出每个单词的个数
.toList
.sortBy(_._2)(Ordering[Int].reverse)
.take(3)

println(wordCountList)

println("================================")

// 思路二:直接基于预统计的结果进行转换
// 1. 将字符串打散为单词,并结合对应的个数包装成二元组
val preCountList: List[(String, Int)] = tupleList.flatMap(
tuple => {
val strings: Array[String] = tuple._1.split(" ")
strings.map( word => (word, tuple._2) )
}
)
println(preCountList)

// 2. 对二元组按照单词进行分组
val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy( _._1 )
println(preCountMap)

// 3. 叠加每个单词预统计的个数值
val countMap: Map[String, Int] = preCountMap.mapValues(
tupleList => tupleList.map(_._2).sum
)
println(countMap)

// 4. 转换成list,排序取前3
val countList = countMap.toList
.sortWith(_._2 > _._2)
.take(3)
println(countList)
}
}

image-20210405231006757

7.8 队列

1)说明

Scala 也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方 法分别为 enqueue 和 dequeue。

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
object Test19_Queue {
def main(args: Array[String]): Unit = {
// 创建一个可变队列
val queue: mutable.Queue[String] = new mutable.Queue[String]()

queue.enqueue("a", "b", "c")

println(queue)
println(queue.dequeue())
println(queue)
println(queue.dequeue())
println(queue)

queue.enqueue("d", "e")

println(queue)
println(queue.dequeue())
println(queue)

println("==========================")

// 不可变队列
val queue2: Queue[String] = Queue("a", "b", "c")
val queue3 = queue2.enqueue("d")
println(queue2)
println(queue3)

}
}

image-20210405231135813

7.9 并行集合

1)说明

Scala 为了充分使用多核 CPU,提供了并行集合(有别于前面的串行集合),用于多核 环境的并行计算。

2)案例实操

1
2
3
4
5
6
7
8
9
10
11
12
13
object Test20_Parallel {
def main(args: Array[String]): Unit = {
val result: immutable.IndexedSeq[Long] = (1 to 100).map(
x => Thread.currentThread.getId
)
println(result)

val result2: ParSeq[Long] = (1 to 100).par.map(
x => Thread.currentThread.getId
)
println(result2)
}
}

image-20210405231256344