目录
一、 集合简介
1.1 不可变集合继承图
1.2 可变集合继承图
二、数组
2.1 不可变数组
2.2 可变数组
2.3 不可变数组与可变数组的转换
2.4 多维数组
三、 Seq集合(List)
3.1 不可变List
3.2 可变ListBuffer
四、Set集合
4.1 可变Set与不可变Set
五、 Map集合
5.1 可变Map与不可变Map
六、 元组
七、 集合常用函数
7.1 基本属性和常用操作
7.2 衍生集合
7.3 集合计算初级函数
7.4 集合计算高级函数
7.5 普通WordCount案例
7.6 复杂WordCount案例
八、 队列
九 、并行集合
1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。
2)对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包
不可变集合:scala.collection.immutable
可变集合:scala.collection.mutable
3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象
4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象
建议:在操作集合的时候,不可变用符号,可变用方法
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的区别:
(1)IndexedSeq是通过索引来查找和定位,因此速度快,比如String就是一个索引集合,通过索引即可定位
(2)LinearSeq是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找
1)数组
定义:val arr1 = new Array[Int](10) (默认0)
(1)new是关键字
(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any
(3)(10),表示数组的大小,确定后就不可以变化
2)案例实操
object Test03 {
def main(args: Array[String]): Unit = {
// 1. 创建数组
// 1.1 直接new
val arr1: Array[Int] = new Array[Int](5) //数组默认为0
//1.2 用伴生对象创建
//val arr2 = Array.apply(1,2,3,4,5)
val arr2 = Array(1,2,3,4,5)
//2.访问数组中元素
println(arr2(4)) //5
println(arr2.apply(4)) //5
//3.数组赋值
arr2(3) = 10
println(arr2.mkString(",")) //1,2,3,10,5
arr1(1) = 23
println(arr1(1)) //23
//4.遍历
//4.1 遍历下标
for( i <- 0 until arr1.length) print(arr1(i))
for( i <- arr1.indices ) println(arr1(i))
//4.2直接遍历数组
for (elem <- arr1 ) println(elem)
//4.2迭代器
val iter = arr2.iterator
while(iter.hasNext)
println(iter.next())
//4.3 调用foreach方法
arr1.foreach((elem: Int) => println(elem))
arr2.foreach(println) //简写
//5 用不可变数组实现添加数组
//需要定义一个新的数组来接收返回值
val newArr1 = arr1 .:+ (27) //追加在后边
val newArr2 = arr2 .+: (13) //添加在最前边
println(newArr1.mkString(","))
println(newArr2.mkString(","))
//添加多个元素
val newArr3 = newArr1 :+ 35 :+ 13
val newArr4 = 21 +: 19 +: newArr2 :+ 56
println(newArr3.mkString(","))
println(newArr4.mkString(","))
}
}
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方法(),支持可变参数
object Test04 {
def main(args: Array[String]): Unit = {
//1. 创建可变数组
val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
val arr2 = ArrayBuffer(1, 2, 3)
println(arr1) //ArrayBuffer()
println(arr2) //ArrayBuffer(1, 2, 3)
//2. 访问数组元素
println(arr2(2)) //3
arr2(2) = 15
arr2.update(1, 27)
println(arr2) //ArrayBuffer(1, 27, 15)
// 3. 向数组添加元素
val newArral1 = arr1 :+ 23
val newArral2 = 12 +: arr2
println(arr1) //ArrayBuffer()
println(arr2) //ArrayBuffer(1, 27, 15)
println(newArral1) //ArrayBuffer(23)
println(newArral2) //ArrayBuffer(12, 1, 27, 15)
println("-------------")
//调用带英文名称的方法
arr1.append(13)
arr2.append(24, 78)
arr1.prepend(36, 92)
arr1.insert(1, 22, 18)
println(arr1) //ArrayBuffer(36, 22, 18, 92, 13)
println(arr2) //ArrayBuffer(1, 27, 15, 24, 78)
arr1 += 31
13 +=: arr1
println(arr1) //ArrayBuffer(13, 36, 22, 18, 92, 13, 31)
//4.删除数组元素
val n = arr1.remove(2)
println(n) //22
println(arr1) //ArrayBuffer(13, 36, 18, 92, 13, 31)
arr1 -= 13
println(arr1) //ArrayBuffer(36, 18, 92, 13, 31)
// 还可以用++=进行集合合并
arr2 ++= ArrayBuffer(23, 45, 67)
Array(12, 56) ++=: arr2
println(arr2) //ArrayBuffer(12, 56, 1, 27, 15, 24, 78, 23, 45, 67)
// 5. 可变数组和不可变数组的转换
// 5.1 可变转不可变
val arr: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
val newArr: Array[Int] = arr.toArray
// 5.2 不可变转可变
val buffer: mutable.Buffer[Int] = newArr.toBuffer
println(buffer) //ArrayBuffer(1, 2, 3)
//5.2 不可变转可变(利用空的转变成可变)
val bArr = ArrayBuffer[Int]()
bArr ++= newArr
println(bArr)
}
}
1)说明
arr1.toBuffer //不可变数组转可变数组
arr2.toArray //可变数组转不可变数组
(1)arr2.toArray返回结果才是一个不可变数组,arr2本身没有变化
(2)arr1.toBuffer返回结果才是一个可变数组,arr1本身没有变化
2)案例实操
// 5. 可变数组和不可变数组的转换
// 5.1 可变转不可变
val arr: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
val newArr: Array[Int] = arr.toArray
// 5.2 不可变转可变
val buffer: mutable.Buffer[Int] = newArr.toBuffer
println(buffer) //ArrayBuffer(1, 2, 3)
//5.2 不可变转可变(利用空的转变成可变)
val bArr = ArrayBuffer[Int]()
bArr ++= newArr
println(bArr)
1)多维数组定义
val arr = Array.ofDim[Double](3,4)
说明:二维数组中有三个一维数组,每个一维数组中有四个元素
2)案例实操
object Test05 {
def main(args: Array[String]): Unit = {
// 1. 创建二维数组
val arr: Array[Array[Int]] = Array.ofDim[Int](2,3)
// 2. 访问数组元素
println(arr(0)(1))
arr(0)(1) = 13
println(arr(0)(1))
// 3. 遍历数组
// for ( i <- 0 until arr.length; j <- 0 until arr(i).length)
for (i <- arr.indices; j <- arr(i).indices){
print(arr(i)(j) + "\t")
if (j == arr(i).length - 1) println()
}
arr.foreach(line => line.foreach(println))
// arr.foreach(_.foreach(println))
}
}
1)说明
(1)List默认为不可变集合
(2)创建一个List(数据有顺序,可重复)
(3)遍历List
(4)List增加数据
(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
(6)取指定数据
(7)空集合Nil
object Test06 {
def main(args: Array[String]): Unit = {
// 1. 创建List
val list1: List[Int] = List(1, 2, 3, 4)
println(list1) //List(1, 2, 3, 4)
// 2. 访问List元素,遍历
println(list1(3)) //4
for (elem <- list1) println(elem) // 1 2 3 4
list1.foreach(println) // 1 2 3 4
// 3. 向列表里添加数据
val list2 = 10 +: list1
val list3 = list2 :+ 24
println(list1) //List(1, 2, 3, 4)
println(list2) //List(10, 1, 2, 3, 4)
println(list3) //List(10, 1, 2, 3, 4, 24)
// 4. 特殊的List,以及用它来构建列表
val list4 = list1.::(52)
val list5 = Nil.::(12)
println(list4) //List(52, 1, 2, 3, 4)
println(list5) //List(12)
val list6 = 13 :: list5
val list7 = 15 :: 24 :: 67 :: Nil
println(list6) //List(13, 12)
println(list7) //List(15, 24, 67)
// 5. 扁平化
val list8: List[Any] = list6 :: list7
println(list8) //List(List(13, 12), 15, 24, 67)
val list9: List[Int] = list6 ::: list7
println(list9) //List(13, 12, 15, 24, 67)
val list10 = list6 ++ list7
println(list10) //List(13, 12, 15, 24, 67)
}
}
1)说明
(1)创建一个可变集合ListBuffer
(2)向集合中添加数据
(3)打印集合数据
2)案例实操
object Test07 {
def main(args: Array[String]): Unit = {
// 1. 创建可变List
val list1: ListBuffer[Int] = new ListBuffer[Int]()
val list2 = ListBuffer(1,2,3)
// 2. 添加数据
list1.append(12) //ListBuffer(12)
list2.append(23,57) //ListBuffer(1, 2, 3, 23, 57)
list1.append(13,22) //ListBuffer(12, 13, 22)
list1 += 65 += 39 //ListBuffer(12, 13, 22, 65, 39)
11 +=: list2 //ListBuffer(11, 1, 2, 3, 23, 57)
println(list1)
println(list2)
// 3. 合并List
val list3 = list1 ++ list2
list1 ++= list2
list1 ++=: list2
println(list1) //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57)
println(list2) //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57, 11, 1, 2, 3, 23, 57)
println(list3) //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57)
// 4. 修改元素
list3(2) = 33
list3.update(4,55)
println(list3) //ListBuffer(12, 13, 33, 65, 55, 11, 1, 2, 3, 23, 57)
// 5. 删除元素
list3.remove(6,2) //ListBuffer(12, 13, 33, 65, 55, 11, 3, 23, 57)
val list4 = list3 - 33 //ListBuffer(12, 13, 65, 55, 11, 3, 23, 57)
list3 -= 23 //ListBuffer(12, 13, 33, 65, 55, 11, 3, 57)
println(list4)
println(list3)
}
}
默认情况下,Scala使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包
1)说明
(1)Set默认是不可变集合,数据无序,创建可变集合mutable.Set(向集合中添加元素,返回一个新的Set)
(2)数据不可重复
(3)遍历集合
2)案例实操
object Test09 {
def main(args: Array[String]): Unit = {
// 1. 不可变Set
// 1.1 创建
val set1: Set[Int] = Set(1, 4, 2, 5, 5, 27, 67)
println(set1) //Set(5, 1, 2, 27, 67, 4)
// 1.2 添加元素
val set2 = set1 + 21
println(set1) //Set(5, 1, 2, 27, 67, 4)
println(set2) //Set(5, 1, 21, 2, 27, 67, 4)
//1.3 合并set
val set3 = Set(1,27,43,79)
val set4 = set2 ++ set3
println(set4) //Set(5, 1, 21, 2, 27, 67, 43, 4, 79)
// 1.4 删除元素
val set5 = set4 - 21
println(set5) //Set(5, 1, 2, 27, 67, 43, 4, 79)
// 2. 可变Set
// 2.1 创建
val set6: mutable.Set[Int] = mutable.Set(1,2,3,4)
// 2.2 添加元素
set6.add(35)
println(set6.add(1)) //false
// 2.3 删除元素
println(set6.remove(2))
println(set6) //Set(1, 35, 3, 4)
set6 -=2
val set7 = set6 - 2
// 2.4 合并集合
val set8 = set6 ++ set1
println(set6)
println(set8)
set6 ++= set1
println(set6)
}
}
Scala中的Map和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射
1)说明
2)案例实操
object Test08 {
def main(args: Array[String]): Unit = {
// 1. 不可变Map
// 1.1 创建
val map1: Map[String, Int] = Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4)
println(map1)
// 1.2 遍历map元素
map1.foreach(println) //(a,1)(b,2)(c,3)(d,4)
map1.keys.foreach(println) //abcd
map1.values.foreach(println) //1234
println("*************")
// 1.3 单独访问元素
println(map1.get("c").getOrElse(0)) //3
println(map1.getOrElse("c", 0)) // 3
// 2. 可变Map
// 2.1 创建
val map2: mutable.Map[String, Int] = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4)
// 2.2 添加元素
map2.put("d", 67)
map2.put("e", 13)
map2 += ("f" -> 25)
println(map2)
// 2.3 修改和删除
map2.update("d", 31)
println(map2("d"))
map2("b") = 69
map2.remove("c")
map2 -= "c"
map2 .-= ("c","d")
println(map2)
// 2.4 合并两个Map
val map3 = map1 ++ map2
map2 ++= map1
println(map1)
println(map2)
println(map3)
}
}
1)说明
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。
注意:元组中最大只能有22个元素。
2)案例实操
(1)声明元组的方式:(元素1,元素2,元素3)
(2)访问元组
(3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶
object Test08_Tuple {
def main(args: Array[String]): Unit = {
// 1. 创建一个元组
val tuple1: (Int, String, Double, Char) = (100, "hello", 12.3, 'c')
println(tuple1)
// 2. 访问元组数据
//(2.1)通过元素的顺序进行访问,调用方式:_顺序号
println(tuple1._3)
// tuple1._2 = "" // error, 不能重新赋值
//(2.2)通过索引访问数据
println(tuple1.productElement(0))
// 3. 遍历数据
// for( elem <- tuple1 ) println(elem) // 元组中没有foreach方法
// tuple1.foreach()
//通过迭代器访问数据
for( elem <- tuple1.productIterator) println(elem)
// 4. 元组和map的键值对 //Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶
// val map1 = Map("a"->1, "b"->2, "c"->3)
// println(map1)
val map1 = Map(("a",1), ("b",2), ("c",3))
map.foreach(tuple=>{println(tuple._1 + "=" + tuple._2)})
// 5. 嵌套元组
val tuple2: (Int, Double, String, List[Int], (Char, Int)) = (12, 0.9, "hi", List(1, 2), ('c', 15))
println(tuple2._5._2)
val tuple3 = (1,1,2,2)
val tuple4 = (("a", 1), ("a", 2))
println(tuple4)
}
}
1)说明
(1)获取集合长度
(2)获取集合大小
(3)循环遍历
(4)迭代器
(5)生成字符串
(6)是否包含
2)案例实操
object TestList {
def main(args: Array[String]): Unit = {
val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
//(1)获取集合长度
println(list.length)
//(2)获取集合大小,等同于length
println(list.size)
//(3)循环遍历
list.foreach(println)
//(4)迭代器
for (elem <- list.itera tor) {
println(elem)
}
//(5)生成字符串
println(list.mkString(","))
//(6)是否包含
println(list.contains(3))
}
}
1)说明
(1)获取集合的头
(2)获取集合的尾(不是头的就是尾)
(3)集合最后一个数据
(4)集合初始数据(不包含最后一个)
(5)反转
(6)取前(后)n个元素
(7)去掉前(后)n个元素
(8)并集
(9)交集
(10)差集
(11)拉链
(12)滑窗
2)案例实操
object Test05 {
def main(args: Array[String]): Unit = {
val list1 = List(1,2,3,4,5,6,6,7)
val list2 = List(5,4,6,7,8,9,10,11,12)
// (1)获取集合的头
println(list1.head) //1
// (2)获取集合的尾(不是头的就是尾)
println(list1.tail) //List(2, 3, 4, 5, 6, 6, 7)
// (3)集合最后一个数据
println(list1.last) //7
// (4)集合初始数据(不包含最后一个)
println(list2.init) //List(5, 4, 6, 7, 8, 9, 10, 11)
// (5)反转
println(list2.reverse) //List(12, 11, 10, 9, 8, 7, 6, 4, 5)
// (6)取前(后)n个元素
println(list1.take(3)) //List(1, 2, 3)
println(list2.takeRight(3)) //List(10, 11, 12)
// (7)去掉前(后)n个元素
println(list1.drop(3)) //List(4, 5, 6, 6, 7)
// (8)并集
val union = list1.union(list2)
println(union) //List(1, 2, 3, 4, 5, 6, 6, 7, 5, 4, 6, 7, 8, 9, 10, 11, 12)
println(list2.union(list1)) //List(5, 4, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 6, 7)
//set的并集去重的,set本身数据无序,不可重复
val set1 = Set(1,2,3,4,5,6,7)
val set2 = Set(4,5,6,7,8,9,10,11,12)
val unionSet = set1.union(set2)
println(unionSet) //Set(5, 10, 1, 6, 9, 2, 12, 7, 3, 11, 8, 4)
println(set2.union(set1)) //Set(5, 10, 1, 6, 9, 2, 12, 7, 3, 11, 8, 4)
// (9)交集
val intersectionSet: Set[Int] = set1.intersect(set2)
println(intersectionSet) //Set(5, 6, 7, 4)
println(list1.intersect(list2)) //List(4, 5, 6, 7)
println(list2.intersect(list1)) //List(5, 4, 6, 7)
// (10)差集
println(list1.diff(list2)) //List(1, 2, 3, 6)
println(list2.diff(list1)) //List(8, 9, 10, 11, 12)
// (11)拉链
//注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
println(list1.zip(list2))
// (12)滑窗
// 12.1 单参数,步长为1
for(elem <- list2.sliding(5)) println(elem) //List(5, 4, 6, 7, 8) List(4, 6, 7, 8, 9) List(6, 7, 8, 9, 10) List(7, 8, 9, 10, 11) List(8, 9, 10, 11, 12)
// 12.2 两参数,size和步长
for(elem <- list2.sliding(5,3)) println(elem) //List(5, 4, 6, 7, 8) List(7, 8, 9, 10, 11) List(10, 11, 12)
// 12.3 整体滑动
for( elem <- list2.sliding(3,3)) println(elem) //List(5, 4, 6) List(7, 8, 9) List(10, 11, 12)
}
}
1)说明
(1)求和
(2)求乘积
(3)最大值
(4)最小值
(5)排序
2)实操
object TestList {
def main(args: Array[String]): Unit = {
val list: List[Int] = List(1, 5, -3, 4, 2, -7, 6)
//(1)求和
println(list.sum)
//(2)求乘积
println(list.product)
//(3)最大值
println(list.max)
//(4)最小值
println(list.min)
//(5)排序
// (5.1)按照元素大小排序
println(list.sortBy(x => x))
// (5.2)按照元素的绝对值大小排序
println(list.sortBy(x => x.abs))
// (5.3)按元素大小升序排序
println(list.sortWith((x, y) => x < y))
// (5.4)按元素大小降序排序
println(list.sortWith((x, y) => x > y))
}
}
(1)sorted
对一个集合进行自然排序,通过传递隐式的Ordering
(2)sortBy
对一个属性或多个属性进行排序,通过它的类型。
(3)sortWith
基于函数的排序,通过一个comparator函数,实现自定义排序的逻辑。
1)说明
(1)过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化
(4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作
集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group)
按照指定的规则对集合的元素进行分组
(6)简化(归约)
(7)折叠
2)实操
object Test06 {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5,6,7,8,9)
// 1. 过滤
// 筛选所有的偶数
val newList: List[Int] = for ( i <- list if i % 2 ==0) yield i
println(newList) //List(2, 4, 6, 8)
val evenList = list.filter(_ % 2 == 0)
println(evenList) //List(2, 4, 6, 8)
//2.转化/映射==>map
println(list.map(_ * 2 + "data")) //List(2data, 4data, 6data, 8data, 10data, 12data, 14data, 16data, 18data)
println(list.map(x => x + 1)) //List(2, 3, 4, 5, 6, 7, 8, 9, 10)
// 3. 扁平化
val nestedList: List[List[Int]] = List(List(1,2,4),List(3,7,9),List(23,46,67))
val flatList: List[Int] = nestedList.flatten
println(flatList) //List(1, 2, 4, 3, 7, 9, 23, 46, 67)
//4. 扁平映射 ==> 注:flatMap相当于先进行map操作,在进行flatten操作
val stringList: List[String] = List("hello scala", "hello world", "hello atguigu")
println(stringList.map(str => str.split(" ")).flatten) //List(hello, scala, hello, world, hello, atguigu)
println(stringList.flatMap(_.split(" "))) //List(hello, scala, hello, world, hello, atguigu)
// 5. 分组
// 按照奇偶性分组
val groupedMap: Map[String,List[Int]] = list.groupBy(data => if(data % 2 == 0) "偶数" else "奇数")
println(groupedMap)
// 按照字符串首字母分组
val strings: List[String] = List("china","canada","usa","japan","uk")
println(strings.groupBy(_.charAt(0)))
}
}
3)Reduce方法
Reduce简化(归约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。
案例实操
object Test07 {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
// 1. reduce
val res1 = list.reduce((a:Int,b:Int) => a + b)
val res2 = list.reduce(_ + _)
val res3 = list.reduceLeft(_+_)
val res4 = list.reduceRight(_+_)
println(res1) //10
println(res2) //10
println(res3) //10
println(res4) //10
从源码的角度,reduce底层调用的其实就是reduceLeft
// 关于左右规约,减法规约
println(list.reduceLeft(_ - _)) //-8
println(list.reduceRight(_ - _)) //-2
val list2 = List(3,4,5,8,10)
println(list2.reduceLeft(_ - _)) // -24 3-4-5-8-10
println(list2.reduceRight(_ - _)) // 6 3-(4-(5-(8-10)))
//2.fold
val res5 = list.fold(10)(_ - _) // 0 10-1-2-3-4
println(res5)
println(list2.foldRight(11)(_ - _)) // -5 3-(4-(5-(8-(10-11)))
}
}
4)Fold方法
Fold折叠:简化的一种特殊情况。
(1)案例实操:fold基本使用
object TestFold {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
// fold方法使用了函数柯里化,存在两个参数列表
// 第一个参数列表为 : 零值(初始值)
// 第二个参数列表为: 简化规则
// fold底层其实为foldLeft
val i = list.foldLeft(1)((x,y)=>x-y)
val i1 = list.foldRight(10)((x,y)=>x-y)
println(i)
println(i1)
}
}
(2)案例实操:两个集合合并
object TestFold {
def main(args: Array[String]): Unit = {
// 两个Map的数据合并
val map1 = mutable.Map("a"->1, "b"->2, "c"->3)
val map2 = mutable.Map("a"->4, "b"->5, "d"->6)
val map3: mutable.Map[String, Int] = map2.foldLeft(map1) {
(map, kv) => {
val k = kv._1
val v = kv._2
map(k) = map.getOrElse(k, 0) + v
map
}
}
println(map3)
}
}
1)需求
单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
2)需求分析
3)案例实操
object TestWordCount {
def main(args: Array[String]): Unit = {
// 单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
val stringList = List("Hello Scala Hbase kafka", "Hello Scala Hbase", "Hello Scala", "Hello")
// 1) 将每一个字符串转换成一个一个单词
val wordList: List[String] = stringList.flatMap(str=>str.split(" "))
//println(wordList)
// 2) 将相同的单词放置在一起
val wordToWordsMap: Map[String, List[String]] = wordList.groupBy(word=>word)
//println(wordToWordsMap)
// 3) 对相同的单词进行计数
// (word, list) => (word, count)
val wordToCountMap: Map[String, Int] = wordToWordsMap.map(tuple=>(tuple._1, tuple._2.size))
// 4) 对计数完成后的结果进行排序(降序)
val sortList: List[(String, Int)] = wordToCountMap.toList.sortWith {
(left, right) => {
left._2 > right._2
}
}
// 5) 对排序后的结果取前3名
val resultList: List[(String, Int)] = sortList.take(3)
println(resultList)
}
}
方式二
object Test13_WordCount {
def main(args: Array[String]): Unit = {
// 1. 简单版本
val stringList = List(
"hello",
"hello world",
"hello scala",
"hello spark in scala",
"hello flink in scala"
)
// 1.1 按空格切分字符串,得到打散的word
val wordList0 = stringList.map( str => str.split(" ") )
// println(wordList0.flatten)
val wordList = stringList.flatMap( _.split(" ") )
println(wordList)
// 1.2 按照单词自身作为key分组
val groupMap: Map[String, List[String]] = wordList.groupBy( word => word )
println(groupMap)
// 1.3 对分组的word列表进行length统计,得到(word,count)
val countMap: Map[String, Int] = groupMap.map( kv => (kv._1, kv._2.length) )
println(countMap)
// 1.4 排序取top3
val sortList: List[(String, Int)] = countMap
.toList // 转换成list
// .sortWith( (data1, data2) => data1._2 > data2._2 )
.sortWith( _._2 > _._2 ) // 按照count值从大到小排序
.take(3) // 选取前3
println(sortList)
1)方式一
object TestWordCount {
def main(args: Array[String]): Unit = {
// 第一种方式(不通用)
val tupleList = List(("Hello Scala Spark World ", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))
val stringList: List[String] = tupleList.map(t=>(t._1 + " ") * t._2)
//val words: List[String] = stringList.flatMap(s=>s.split(" "))
val words: List[String] = stringList.flatMap(_.split(" "))
//在map中,如果传进来什么就返回什么,不要用_省略
val groupMap: Map[String, List[String]] = words.groupBy(word=>word)
//val groupMap: Map[String, List[String]] = words.groupBy(_)
// (word, list) => (word, count)
val wordToCount: Map[String, Int] = groupMap.map(t=>(t._1, t._2.size))
val wordCountList: List[(String, Int)] = wordToCount.toList.sortWith {
(left, right) => {
left._2 > right._2
}
}.take(3)
//tupleList.map(t=>(t._1 + " ") * t._2).flatMap(_.split(" ")).groupBy(word=>word).map(t=>(t._1, t._2.size))
println(wordCountList)
}
}
2)方式二
object TestWordCount {
def main(args: Array[String]): Unit = {
val tuples = List(("Hello Scala Spark World", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))
// (Hello,4),(Scala,4),(Spark,4),(World,4)
// (Hello,3),(Scala,3),(Spark,3)
// (Hello,2),(Scala,2)
// (Hello,1)
val wordToCountList: List[(String, Int)] = tuples.flatMap {
t => {
val strings: Array[String] = t._1.split(" ")
strings.map(word => (word, t._2))
}
}
// Hello, List((Hello,4), (Hello,3), (Hello,2), (Hello,1))
// Scala, List((Scala,4), (Scala,3), (Scala,2)
// Spark, List((Spark,4), (Spark,3)
// Word, List((Word,4))
val wordToTupleMap: Map[String, List[(String, Int)]] = wordToCountList.groupBy(t=>t._1)
val stringToInts: Map[String, List[Int]] = wordToTupleMap.mapValues {
datas => datas.map(t => t._2)
}
stringToInts
/*
val wordToCountMap: Map[String, List[Int]] = wordToTupleMap.map {
t => {
(t._1, t._2.map(t1 => t1._2))
}
}
val wordToTotalCountMap: Map[String, Int] = wordToCountMap.map(t=>(t._1, t._2.sum))
println(wordToTotalCountMap)
*/
}
}
2)方式三
object Test10 {
def main(args: Array[String]): Unit = {
val tupleList: List[(String, Int)] = List(
("hello world", 1),
("hello scala", 2),
("hello spark in scala", 3),
("hello flink in scala", 4)
)
val wordCountMap1 = tupleList.flatMap(kv =>{
val strList = kv._1.split(" ")
strList.map(word => (word,kv._2))
}) //List((hello,1), (world,1), (hello,2), (scala,2), (hello,3), (spark,3), (in,3), (scala,3), (hello,4), (flink,4), (in,4), (scala,4))
.groupBy(_ ._1 ) //Map(in -> List((in,3), (in,4)), world -> List((world,1)), flink -> List((flink,4)), spark -> List((spark,3)), scala -> List((scala,2), (scala,3), (scala,4)), hello -> List((hello,1), (hello,2), (hello,3), (hello,4)))
.toList // List((in,List((in,3), (in,4))), (world,List((world,1))), (flink,List((flink,4))), (spark,List((spark,3))), (scala,List((scala,2), (scala,3), (scala,4))), (hello,List((hello,1), (hello,2), (hello,3), (hello,4))))
.map(kv => {
(kv._1,kv._2.map(_._2))
}) //List((in,List(3, 4)), (world,List(1)), (flink,List(4)), (spark,List(3)), (scala,List(2, 3, 4)), (hello,List(1, 2, 3, 4)))
.map(kv => (kv._1,kv._2.sum)) //List((in,7), (world,1), (flink,4), (spark,3), (scala,9), (hello,10))
.sortBy(_._2).reverse //List((hello,10), (scala,9), (in,7), (flink,4), (spark,3), (world,1))
.take(3) //List((hello,10), (scala,9), (in,7))
println(wordCountMap1)
}
}
1)说明
Scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。
2)案例实操
object TestQueue {
def main(args: Array[String]): Unit = {
val que = new mutable.Queue[String]()
que.enqueue("a", "b", "c")
println(que.dequeue())
println(que.dequeue())
println(que.dequeue())
}
}
1)说明
Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。
2)案例实操
object TestPar {
def main(args: Array[String]): Unit = {
val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}
val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}
println(result1)
println(result2)
}
}