一、 集合简介
1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。
2)对于几乎所有的集合类,Scala都同时提供了
可变
和
不可变
的版本,分别位于以下两个包
不可变集合:scala.collection.immutable
可变集合:scala.collection.mutable
3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象
4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象
建议:在操作集合的时候,不可变用符号,可变用方法
1.1 不可变集合继承图
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.2 可变集合继承图
2.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(","))
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方法(),支持可变参数
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)
2.3 不可变数组与可变数组的转换
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)
2.4 多维数组
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))
三、 Seq集合(List)
3.1 不可变List
(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)
3.2 可变ListBuffer
(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)
四、Set集合
默认情况下,Scala使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包
4.1 可变Set与不可变Set
(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)
五、 Map集合
Scala中的Map和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射
5.1 可变Map与不可变Map
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)
六、 元组
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。
注意:元组中最大只能有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)
七、 集合常用函数
7.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))
7.2 衍生集合
(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)
7.3 集合计算初级函数
(1)求和
(2)求乘积
(3)最大值
(4)最小值
(5)排序
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函数,实现自定义排序的逻辑。
7.4 集合计算高级函数
(1)过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map)
将集合中的每一个元素映射到某一个函数
(3)扁平化
(4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作
集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group)
按照指定的规则对集合的元素进行分组
(6)简化(归约)
(7)折叠
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
println(map3)
7.5 普通WordCount案例
单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
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)
7.6 复杂WordCount案例
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)
八、 队列
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())
九 、并行集合
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)
一、集合的简介1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。2)对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包不可变集合:scala.collection.immutable可变集合:scala.collection.mutable3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象4)可变集合,就是这个集
Scala 的集合分为三大类序列Seq,集Set 以及映射Map。所有的集合都扩展自 Iterable 特质在 Scala 中集合有可变(“scala.collection.mutable” 包下存放)和不可变(“scala.collection.immutable” 包下存放)两种类型。
var greeting:String = "Hello world!";
每当遇到一个字符串在代码中,编译器创建String对象及其值,在这个示例中使用:“Hello world!”,但如果你喜欢,可以给字符串,因为这里我已经在声明中交替显示。
(1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。
(2)对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包。
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable
(3)不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象
(4)可变集合,就是这个.
object CollectionReview {
def main(args: Array[String]): Unit = {
val ints = List(1,3,2,5,2,4,4)
//contains
println(ints.contains(4))//true
//distinct
println(ints.distinct)//13254
//isEmpty
println(ints.isEmpt
从较高的层次来看 Scala 集合,主要有以下三个类别可供选择:
Sequences是元素的顺序集合,可以是索引的(如数组)或线性的(如链表);
Maps包含键/值对的集合,类似于Java的Map、Python的dict;
Sets是唯一元素的无序集合;
所有这些都是基本类型,并且具有用于特定目的的子类型,例如并发、缓存和流式处理。除了这三个主要类别之外,还有其他有用的集合类型,包括ranges, stacks, queues。
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质,意味着 集合的基本特点是⽀持迭代遍历的。
scala集合两个主要的包:
# 不可变集合
scala.collection.immutable (Scala默认采用.
1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable
2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable
3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而
不会对原对象进行修改。类似于 java 中的 Str
Scala 集合分为可变的和不可变的集合。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用scala.collection.mutable.Set包。
默认引用 scala.collection.immutable.Set,不可变集合实例如下:
1.定义:
var set1 =Set(1,"一",2,"er")
set1.foreach(x => println(x))
1.集合简介
1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable特质。
2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包
不可变集合:scala.collection.immutable
可变集合: scala.collection.mutable
3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。
类似于 java 中的 String 对象
Scala 的集合有三大类: 序列seq, 集Set, 映射Map, 所有的集合都扩展自 Iterable 特质;
对于几乎所有的集合类, Scala都同时提供了可变和不可变的版本. 分别位于以下两个包: scala.collection.immutable, scala.collection.mutable
Q:什么是可变,不可变集合?
a. Scala 不可变集合, 就是指该集合对象不可修