C/C++教程

scala的集合类型

本文主要是介绍scala的集合类型,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、集合类型

集合是⼀种用来存储各种对象和数据的容器。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中⾮常 重要的⼀种数据结构,后⾯会大量使用。其特点包括:

  1. 最多⽀持22个元素组合,分别对应类型Tuple1~Tuple22,相应也称为⼀元组(⼀般不用)、⼆元组、三元组...
  2. 元组可以容纳不同类型的元素
  3. 元组不可变

创建元组:使用小括号 () 将多个元素括起来,元素之间⽤逗号分隔,元素的类型和个数不超过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

这篇关于scala的集合类型的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!