一、集合类型
集合是⼀种用来存储各种对象和数据的容器。Scala 集合分为可变的和不可变的集合。
1. 不可变集合可以安全的并发访问。
2. 可变集合可以在适当的地⽅被更新或扩展。这意味着你可以修改,添加,移除⼀个集合的元素。
Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质,意味着 集合的基本特点是⽀持迭代遍历的。
scala集合两个主要的包:
# 不可变集合
scala.collection.immutable (Scala默认采用不可变集合)
# 可变集合
scala.collection.mutable
分类描述
Seq序列。元素以线性方式存储,集合中可以存放重复对象。
Set集(数据集,区别于集合)。集中的对象不按特定的方式排序,并且没有重复对象。
Map⼀种把键对象和值对象映射的集合,它的每⼀个元素都包含⼀对键对象和值对象。
对于可变与不可变集合,Seq、Set、Map又有不同的实现方式,下面两张图详细描述了其继承关系。
1.数组
任何数组都是可变集合
数组包括:Array(定长)和ArrayBuffer(变长)
# Array
- 定长数组,数组不可扩容 scala.Array
# ArrayBuffer
- 变长数组,数组可扩容 scala.collection.mutable.ArrayBuffer
val arr=Array(1,2,3) val arr1=new Array(100) scala> arr :+ 4 //+: res306:
Array[Int] = Array(1, 2, 3, 4) arr是定长数组,不能修改长度,这里是返回新的数组,原数组并没有被修改
# 什么时候用new
如果没有提供object的apply方法时,class必须用new.
定长数组
arr是定长数组,不能改变长度
定⻓数组是不可变集合吗? 不是。定长数组是可变集合的⼀种,内容可变,但是其长度不可变。
# 扩展:为什么定长数组是可变集合?
Array本身不属于scala集合成员,从前⾯类继承图中也可发现这⼀点,在可变集合图中IndexedSeq有⼀条虚线指向了Array,说明并不是直接继承关系。
⼀般将Array归为集合是因为Scala默认将Array隐式转换为WrappedArray,⽽WrappedArray实现了IndexedSeq特质。
从这⼀点上来说,String与WrappedString也有异曲同⼯之妙,可以发现在不可变集合中,String与IndexedSeq也是虚线连接,也就是说在Scala中,String可以当集合处理。参考下⽂中的描述,请⾃⾏通过源码验证。
Array被隐式转换为WrappedArray(scala.collection.mutable.WrappedArray),间接拥有了集合的特征。
//Predef.scala 提示:所有scala⽂件默认导⼊Predef对象 implicit def genericWrapArray[T](xs:
Array[T]): WrappedArray[T] = if (xs eq null) null else WrappedArray.make(xs)
变长数组 ArrayBuffer
# ArrayBuffer的创建
1)直接创建
2)由Array转化
# 由arr转化 arr.toBuffer scala> arr.toBuffer res286:
scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3) scala>
arr.toBuffer+=4 res287: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1,
2, 3, 4) scala> res286 res289: scala.collection.mutable.Buffer[Int] =
ArrayBuffer(1, 2, 3) scala> res287 res290: scala.collection.mutable.Buffer[Int]
= ArrayBuffer(1, 2, 3, 4) # 直接创建 scala> import
scala.collection.mutable.ArrayBuffer import
scala.collection.mutable.ArrayBuffer scala> val arrBuff=ArrayBuffer(1, 2, 3)
arrBuff: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
小结:ArrayBuffer是在原来的Buffer上修改.
+: 返回新的对象
+= 是在原对象上修改
Array(1,2,3,4,5).filter(_%2==0).map(_*2).foreach(println)
2 元组
Scala Tuple表示固定元素的组合,元组可以装着多个不同类型的值,是不同类型的值的聚集。Tuple是Scala中⾮常
重要的⼀种数据结构,后⾯会大量使用。其特点包括:
* 最多⽀持22个元素组合,分别对应类型Tuple1~Tuple22,相应也称为⼀元组(⼀般不用)、⼆元组、三元组...
* 元组可以容纳不同类型的元素
* 元组不可变
创建元组:使用小括号 () 将多个元素括起来,元素之间⽤逗号分隔,元素的类型和个数不超过22。
访问组元:使用 _1 , _2 , _3 等形式访问组元,注意下标从1开始。
scala> val stu=(101,"oak","male",24) stu: (Int, String, String, Int) =
(101,oak,male,24) scala> stu._1 res0: Int = 101 scala> stu._2 res1: String = oak
注意和同时定义多个变量的区别
scala> val (x,y,m,n)=(100,"jason","man",100) x: Int = 100 y: String = jason m:
String = man n: Int = 100
元组不能修改
scala> stu._3="xx" <console>:15: error: reassignment to val stu._3="xx"
因为元组不是集合,所以不能直接遍历,需要间接转换为集合进行遍历。
scala> for(i<-stu)println(i) <console>:17: error: value foreach is not a
member of (Int, String, String, Int) for(i<-stu)println(i) ^ scala>
for(i<-stu.productIterator)println(i) 100 jason man 100
Traversable(可以重复遍历) & TraversableOnce(只能遍历一次) 的区别
元组对应的类型为 Tuple1-Tuple22
为什么没有Tuple0? ()
特别地:Tuple2 常用于表示对偶,可以表示Map中的⼀个元素,Map是K/V对偶的集合,对偶是元组的最简单形式。
scala> (1,("jason","man")) res349: (Int, (String, String)) = (1,(jason,man))
scala> (1,Array("jason","man")) res350: (Int, Array[String]) = (1,Array(jason,
man)) scala> val tp2=Tuple2(1,2) tp2: (Int, Int) = (1,2) scala> val
tp2="a"->100 tp2: (String, Int) = (a,100)
样例类的创建
scala> case class student(id: Int,name: String) defined class student
拉链操作:
元组需要转换为集合进行拉链操作
scala> val tp3=(1,2,3) tp3: (Int, Int, Int) = (1,2,3) scala> val tp3_1=(1,2,3)
tp3_1: (Int, Int, Int) = (1,2,3) scala> tp3.productIterator.toList zip
tp3_1.productIterator.toList res364: List[(Any, Any)] = List((a,1), (b,2),
(c,3)) scala> Array("a","b").zipAll(Array(1,2,3),"",0) res367: Array[(String,
Int)] = Array((a,1), (b,2), ("",3)) scala>
Array("a","b","c").zipAll(Array(1,2),"",0) res2: Array[(String, Int)] =
Array((a,1), (b,2), (c,0)) scala> List(("a",1), ("b",2), ("c",0)).unzip res5:
(List[String], List[Int]) = (List(a, b, c),List(1, 2, 0)) 最常用的方法: scala>
Array("a","b").zipWithIndex res6: Array[(String, Int)] = Array((a,0), (b,1))
scala> Array("a","b").zipWithIndex.foreach(x=>println(x.swap)) (0,a) (1,b)
3 映射(Map)
3.1 不可变Map的创建
scala> val scores = Map("zhangsan"->70,"lisi"->80,"wangwu"->90) scores:
scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 70, lisi -> 80,
wangwu -> 90) # 无法修改Map中的值 scala> scores("zhangsan")=91 <console>:16: error:
value update is not a member of scala.collection.immutable.Map[String,Int]
scores("zhangsan")=91 scala> scores.keys res384: Iterable[String] =
Set(zhangsan, lisi, wangwu) scala> scores.values res385: Iterable[Int] =
MapLike(90, 80, 70)
取值
scala> scores.get("zhangsan") res390: Option[Int] = Some(90) scala>
scores.get("zhangsan").get res391: Int = 90 # 推荐使用 scala>
scores.getOrElse("zhangsan",0) res392: Int = 90
移除n个元素
# 移除0个元素 scala> scores.drop(0) res393:
scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 90, lisi -> 80,
wangwu -> 70) scala> scores.drop(1) res394:
scala.collection.immutable.Map[String,Int] = Map(lisi -> 80, wangwu -> 70)
scala> scores.drop(2) res395: scala.collection.immutable.Map[String,Int] =
Map(wangwu -> 70) # 不可变map不发生变化 scala> scores res396:
scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 90, lisi -> 80,
wangwu -> 70)
添加元素
//map 没有+:操作,只有 + scala> scores + ("d"->5) res404:
scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 90, lisi -> 80,
wangwu -> 70, d -> 5) # 未发生变化 scala> scores res405:
scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 90, lisi -> 80,
wangwu -> 70)
遍历操作
# 注意以下两种方式的区别 scala> for(kv<-scores) println(kv) (zhangsan,90) (lisi,80)
(wangwu,70) scala> for((k,v)<-scores) println(k,v) (zhangsan,90) (lisi,80)
(wangwu,70) scala> for(kv<-scores) println(kv._1) zhangsan lisi wangwu scala>
for(kv<-scores) println(kv._2) 90 80 70 scala> scores foreach println
(zhangsan,90) (lisi,80) (wangwu,70)
注意:map的默认实现就是HashMap
scala> val scores =
scala.collection.immutable.HashMap("zhangsan"->90,"lisi"->80,"wangwu"->70,"zhaoliu"->66,"xx"->88)
scores: scala.collection.immutable.HashMap[String,Int] = Map(xx -> 88, lisi ->
80, zhaoliu -> 66, wangwu -> 70, zhangsan -> 90) scala> val scores =
scala.collection.immutable.TreeMap("zhangsan"->90,"lisi"->80,"wangwu"->70,"zhaoliu"->66,"xx"->88)
scores: scala.collection.immutable.TreeMap[String,Int] = Map(lisi -> 80, wangwu
-> 70, xx -> 88, zhangsan -> 90, zhaoliu -> 66)
HashMap和TreeMap的转换
# 直接转换 无效 scala> scores.asInstanceOf[TreeMap[String,Int]]
java.lang.ClassCastException: scala.collection.mutable.HashMap cannot be cast
to scala.collection.immutable.TreeMap ... 32 elided # 先创建TreeMap 再遍历HashMap添加
scala> var tm=TreeMap[String,Int]() scala> scores.foreach(kv=>tm=tm+(kv))
scala> tm res439: scala.collection.immutable.TreeMap[String,Int] = Map(a -> 1,
lisi -> 80, wangwu -> 70, xx -> 88, zhangsan -> 90, zhaoliu -> 66)
3.2 创建可变Map
== 可变Map使用较多 ==
scala> val scores =
scala.collection.mutable.Map("zhangsan"->90,"lisi"->80,"wangwu"->70,"zhaoliu"->66,"xx"->88)
scores: scala.collection.mutable.Map[String,Int] = Map(lisi -> 80, zhangsan ->
90, zhaoliu -> 66, xx -> 88, wangwu -> 70) scala> val scores =
scala.collection.mutable.HashMap("zhangsan"->90,"lisi"->80,"wangwu"->70,"zhaoliu"->66,"xx"->88)
scores: scala.collection.mutable.HashMap[String,Int] = Map(lisi -> 80, zhangsan
-> 90, zhaoliu -> 66, xx -> 88, wangwu -> 70) scala> scores.get("lisi") res441:
Option[Int] = Some(80) scala> scores("lisi")=91 scala> scores.get("lisi")
res443: Option[Int] = Some(91)
添加元素
//推荐使用 scala> scores.put("a",1) res444: Option[Int] = None scala> scores
res445: scala.collection.mutable.Map[String,Int] = Map(lisi -> 91, zhangsan ->
90, a -> 1, zhaoliu -> 66, xx -> 88, wangwu -> 70) // + 返回的是新的map对象 scala>
scores + ("b"->2) res446: scala.collection.mutable.Map[String,Int] = Map(b ->
2, lisi -> 91, zhangsan -> 90, a -> 1, zhaoliu -> 66, xx -> 88, wangwu -> 70) #
原来的Map未发生改变 scala> scores res447: scala.collection.mutable.Map[String,Int] =
Map(lisi -> 91, zhangsan -> 90, a -> 1, zhaoliu -> 66, xx -> 88, wangwu -> 70)
4 列表(List)
4.1 List 不可变
scala> List(1,2,3) res451: List[Int] = List(1, 2, 3) scala> (1 to 100) toList
warning: there was one feature warning; re-run with -feature for details
res452: List[Int] = List(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) # 数组 scala> Array(1,2,3).toList res453: List[Int] = List(1, 2,
3) # 元组 scala> (1,2,3).productIterator.toList res455: List[Any] = List(1, 2, 3)
scala> Map("a"->1).toList res456: List[(String, Int)] = List((a,1)) scala>
Seq(1,2,3) res457: Seq[Int] = List(1, 2, 3) scala> 9 :: 5 :: 2 :: Nil res464:
List[Int] = List(9, 5, 2) scala> List(1):::List(2) res470: List[Int] = List(1,
2) scala> val lst1=List(1) lst1: List[Int] = List(1) scala> lst1:+123 res473:
List[Int] = List(1, 123) scala> lst1 res474: List[Int] = List(1) # 没有new
List(100)这种写法 了解实际上List这样创建出来的 scala> List(1,2,3).getClass res496: Class[_ <:
List[Int]] = class scala.collection.immutable.$colon$colon scala>
$colon$colon(1,$colon$colon(2,$colon$colon(3,Nil))) res500:
scala.collection.immutable.::[Int] = List(1, 2, 3) # new
scala.collection.immutable.::(x, this)
4.2 ListBuffer 可变
scala> import scala.collection.mutable.ListBuffer import
scala.collection.mutable.ListBuffer scala> val buf=ListBuffer(1,2,3) buf:
scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3) # :+ 返回新的对象
scala> buf:+4 res475: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1,
2, 3, 4) scala> buf res476: scala.collection.mutable.ListBuffer[Int] =
ListBuffer(1, 2, 3) # += 在原来的List上更改 scala> buf+=4 res478: buf.type =
ListBuffer(1, 2, 3, 4) scala> buf res479:
scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4) scala>
buf++=ListBuffer(7,8) res482: buf.type = ListBuffer(1, 2, 3, 4, 7, 8) scala>
buf res483: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4,
7, 8)
5 Set
Set中的元素不可重复,无序(TreeSet除外)
5.1 创建不可变Set
scala> import scala.collection.immutable.HashSet import
scala.collection.immutable.HashSet scala> val set0=Set(1,2,3,4,5) set0:
scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4) scala>
println(set0.getClass) class scala.collection.immutable.HashSet$HashTrieSet #
默认的Set scala> val set1 = new HashSet[Int]() set1:
scala.collection.immutable.HashSet[Int] = Set() # 可以使⽤加号追加元素,会产⽣⼀个新的集合,原有set不变
scala> val set2 = set1 + 1 set2: scala.collection.immutable.HashSet[Int] =
Set(1) scala> set1 res3: scala.collection.immutable.HashSet[Int] = Set() #
Set集合中不会出现重复的元素 scala> val set3 = set2 ++ Set(1,2,3) set3:
scala.collection.immutable.HashSet[Int] = Set(1, 2, 3) scala> val set4 =
Set(1,2,3,4,5,6) set4: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3,
4) # Set集合中的元素是⽆序的 scala> print(set4) Set(5, 1, 6, 2, 3, 4) # SortedSet中是有序的
scala> val set5=scala.collection.immutable.TreeSet(1,1,10,5,6,7,8,11,13) set5:
scala.collection.immutable.TreeSet[Int] = TreeSet(1, 5, 6, 7, 8, 10, 11, 13)
5.2 创建可变Set
import scala.collection.mutable object MutSetDemo extends App{ val mutableSet
= Set(1,2,3) println(mutableSet.getClass.getName) //
scala.collection.mutable.HashSet //创建⼀个可变的HashSet val set1 = new
mutable.HashSet[Int]() //向HashSet中添加元素 set1 += 2 //add等价于+= set1.add(4)
//删除⼀个元素,如果删除的对象不存在,则不⽣效,也不会报错 set1 -= 5 set1.remove(2) println(set1) }
5.3 集合的基本操作
Scala集合有三个基本操作:
* head 返回集合第⼀个元素
* tail 返回⼀个集合,包含除了第⼀元素之外的其他元素
* isEmpty 在集合为空时返回true
查找集合中最⼤与最⼩元素:
可以使⽤ Set.min ⽅法来查找集合中的最⼩元素,使⽤ Set.max ⽅法查找集合中 的最⼤元素。
5.4 两个set之间的常用操作
1)连接两个集合
使⽤ ++ 运算符或 Set.++() ⽅法来连接两个集合。如果元素有重复的就会移除重复的元素。
2)集合的交集
使⽤ Set.&()⽅法或 Set.intersect() 方法来查看两个集合的交集元素。
3)常用方法
* &:交集运算
* &~:差集运算
* union:并集运算
* contains:是否包含某⼀元素,包含返回true,不包含返回false
* count:计算满足指定条件的集合元素个数
* iterator:获得⼀个迭代器,可⽤于集合遍历
* size:返回集合元素的数量
* splitAt:将集合拆分为两个容器,第⼀个由前n个元素组成,第⼆个由剩下的元素组成
* take:返回前n个元素
* takeRight:返回后n个元素
* 使用to{type}转换为其他集合类型
二、集合的应用
1 集合的重要函数
/* 常⽤⽅法 基本上集合中都可以使⽤,极个别使⽤不上 Spark中常⽤的集合: Array List 元组 Map Set */ object
CollectionMethodDemo { def main(args: Array[String]): Unit = { /*
map遍历集合处理集合中数据并返回⼀个全新集合 filter遍历集合提供⼀个函数指定过滤规则,对集合中数据继续过滤,满⾜需求的会被过滤出来形成⼀个新的集合
聚合函数(求和)sum 将集合中每⼀个元素相加求出最终和(具备可加性) --> 数值 max和min 最⼤值和最⼩值(了解)
foreach遍历集合主要是打印集合中数据(也可以操作集合中数据但是不能新的集合) --> 输出 sorted 排序 --> 升序 降序 可以考虑
reverse(翻转) sortwith 需要传⼊⽐较参数,这个参数⽐较会决定是升序还是降序 第⼀个参数 > 第⼆个参数 降序 第⼀个参数 < 第⼆个参数
升序 ps:这些⽅法Array和List基本上都可以使⽤ Map和Set选择使⽤ 元组也是选择使⽤ */ //1.Flatten
可以将存储在集合内部的集合压平 val list:List[List[Int]] =
List(List(1,2,3),List(4,5,6),List(7,8,9)) //List(1,2,3,4,5,6,7,8,9) val
flatten: List[Int] = list.flatten println(flatten) //set集合中提供了特殊的操作 --交集,并集和差集
val num1 = Set(5,6,9,20,30,45) val num2= Set(50,60,9,20,35,55) //交集
println(num1.intersect(num2)) //并集 println(num1.union(num2)) //差集
println(num1.diff(num2)) //forall 对集合中的元素条件进⾏过滤,只有当所有元素都满⾜要求时,才会返回true
否则返回false val list1 = List(1,2,3,4,5) val bool:Boolean = list1.forall(_ < 3)
//Partition 分区 //ps:Scala中只能模拟,Spark中可以做到这个分区 //根据传⼊的函数 将数据吸⼊到不同存储位置中 val list2
= List(1,2,3,4,5,6) //返回值类型是⼀个元组 val tuple: (List[Int], List[Int]) =
list2.partition(_%2 ==0) val list2_1 = tuple._1 //两个聚合函数 //1. fold 求和
⽐较特殊需要两个参数 ⼀个是默认值,另外⼀个是计算逻辑 // 当前fold是典型的 柯⾥化 val list3 = List(1,2,3,4,5) //计算
//[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 //现在属于是单线程,效果是看出来, 使⽤par的时候会出现多线程状态
val sum = list3.fold(2)((res,n)=>res+n) println(sum) //fold有两个变种 foldleft 和
foldright //2.reduce 直接求和 通过计算逻辑 进⾏集合中数据的计算 val list4 = List(1,2,3,4,5) val
sum2 = list4.reduce((x,y)=>x+y) //reduce也有两个变种 reduceleft 和 reduceright } }
2 并行集合
Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。 主要用到的算法有:
# Divide and conquer :
分治算法,Scala通过splitters,combiners等抽象层来实现,主要原理是将计算⼯作分解很多任务,分发给⼀些处理器去完成,并将它们处理结果合并返回
# Work
stealin:工作窃取算法,主要⽤于任务调度负载均衡(load-balancing),通俗点完成⾃⼰的所有任务之后,发现其他⼈还有活没⼲完,主动(或被安排)帮他⼈⼀起⼲,这样达到尽早⼲完的⽬的。
1)打印1~5
scala> (1 to 5).foreach(println(_)) 1 2 3 4 5 scala> println() scala> (1 to
5).par.foreach(println(_)) 3 1 4 2 5
2) 查看并行集合中元素访问的线程
scala> val result1 = (0 to 10000).map{case _ =>
Thread.currentThread.getName}.distinct result1:
scala.collection.immutable.IndexedSeq[String] = Vector(main) scala> val result2
= (0 to 10000).par.map{case _ => Thread.currentThread.getName}.distinct
result2: scala.collection.parallel.immutable.ParSeq[String] =
ParVector(ForkJoinPool-1-worker-25, ForkJoinPool-1-worker-23,
ForkJoinPool-1-worker-29, ForkJoinPool-1-worker-13, ForkJoinPool-1-worker-31,
ForkJoinPool-1-worker-21, ForkJoinPool-1-worker-11, ForkJoinPool-1-worker-15,
ForkJoinPool-1-worker-3, ForkJoinPool-1-worker-19, ForkJoinPool-1-worker-1,
ForkJoinPool-1-worker-5, ForkJoinPool-1-worker-17, ForkJoinPool-1-worker-9,
ForkJoinPool-1-worker-7, ForkJoinPool-1-worker-27) scala> println(result1)
Vector(main) scala> println(result2) ParVector(ForkJoinPool-1-worker-25,
ForkJoinPool-1-worker-23, ForkJoinPool-1-worker-29, ForkJoinPool-1-worker-13,
ForkJoinPool-1-worker-31, ForkJoinPool-1-worker-21, ForkJoinPool-1-worker-11,
ForkJoinPool-1-worker-15, ForkJoinPool-1-worker-3, ForkJoinPool-1-worker-19,
ForkJoinPool-1-worker-1, ForkJoinPool-1-worker-5, ForkJoinPool-1-worker-17,
ForkJoinPool-1-worker-9, ForkJoinPool-1-worker-7, ForkJoinPool-1-worker-27)
3 WordCount
/** * 单词统计 */ object Scala_WordCount { def main(args: Array[String]): Unit = {
//数据 val line = List("hello tom hello jerry","hello xiaobai hello","hello tom")
// 要求将数据进⾏处理得到的结果
//List("hello","tom","hello","jerry","hello","xiaobai","hello","hello","tom")
/*flatten+Map实现 val words: List[Array[String]] = line.map(_.split(" ")) val
flatten: List[String] = words.flatten println(flatten) */ //1.flatMap -->
flatten+Map 具备在遍历处理数据同时,将数据将数据进⾏扁平化处理 //在处理数据的时候⼀定要返回⼀个集 val words:List[String]
= line.flatMap(_.split(" ")) println(words) // 可以仿照MR中Map阶段,对单词拼接形成kv键值对 单词,1
val tuples: List[(String, Int)] = words.map((_,1)) println(tuples)
//MR中kv键值对会发送到Reduce然后会出现相同key为⼀组计算⼀次reduce
//因为处理是单词,仿照MR中Reduce端处理逻辑,相同key在⼀起,Scala中提供groupBy根据传⼊参数进⾏分组 //返回值时⼀个Map val
grouped: Map[String, List[(String, Int)]] = tuples.groupBy(_._1)
println(grouped) //Map的组成是 key 是单词 value是具体的单词对应元组 其中元组是使⽤List存储
//此时只需要知道key所对应value中List元素的个数,就可以知道当前单词的个数了
//mapValues是处理Map集合中value的值,只操作value,原则是对应key的value值,返回值是⼀个Map[key是原有的可以,value是计算结果之后的value]
val sumed: Map[String, Int] = grouped.mapValues(_.size) println(sumed) val
list: List[(String, Int)] = sumed.toList /** * sortBy分为两种⼀种是Scala版本
另外⼀种是Spark版本 * Scala版本在没有使⽤隐式转换⾃定义的前提下,sortBy只能升序不能降序 * Spark版本中sortBy有两个参数
⼀个是根据谁来排序, 第⼆个参数是Boolean类型 true是升序 false降序 */ //参数是⼀个⽐较原则 val sorted:
List[(String, Int)] = list.sortBy(_._2) //topN 降序排序 val top1 = sorted take 1
println(sorted) //简化版本 //line.flatMap(_.split(" ")).map((_,1)) //
.groupBy(_._1).mapValues(_.size).toList.sortBy(_._2).take(1) } }
4 Java和Scala集合的互操作
# Scala中的集合和Java中集合互相转换 引⽤⼀个包即可 import scala.collection.JavaConverters._ #
将Scala集合转换为Java集合 val list:java.util.List[Int]=List(1,2,3,4,5).asJava #
将Java集合转换为Scala val buffer: mutable.Buffer[Int] = list.asScala # toXXX
转换成需要的集合类型即可 --> XXX是集合名字 例如Array