Scala进阶之路-高级数据类型之集合的使用

            Scala进阶之路-高级数据类型之集合的使用

                               作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

  Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable 特质在 Scala 中集合有可变(scala.collection.mutable” 包下存放)和不可变(scala.collection.immutable” 包下存放)两种类型,immutable 类型的集合初始化后就不能改变了(注意与 val 修饰的变量进行区别)。

Scala进阶之路-高级数据类型之集合的使用

一.Seq  序列

1>.不可变的序列 import scala.collection.immutable._

  1 /*
  2 @author :yinzhengjie
  3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  4 EMAIL:y1053419035@qq.com
  5 */
  6 package cn.org.yinzhengjie.function
  7 
  8 object SetOperation {
  9     def main(args: Array[String]): Unit = {
 10         //定义一个list
 11         var list = List("yinzhengjie","Python","Golang","Java","Scala")
 12         //查看list的头
 13         print(s"list.head=====> ${list.head}
")
 14         //查看list的尾,尾就是出了头部的数据
 15         print(s"list.tail=====> ${list.tail}
")
 16         //Nil表示为空,此时的list为空
 17         list = Nil
 18         print(s"list=====> ${list}
")
 19         /**
 20           *     "::" 操作符是将给定的头和尾创建一个新的列表。
 21           *     注意,"::" 操作符是右结合的,如 100::200::300::Nil 相当于 100::(200::(300::Nil))
 22           */
 23         var list2 = 100::200::300::list
 24         println("list2=====>"+list2)
 25         //“+”是拼接操作
 26         var list3 = list2 + ("666666")
 27         print(s"list3=====> ${list3}
")
 28         //“++”是将两个集合进行拼接操作,最终会返回一个新的list对象,将右边的集合的每一个元素追加在左边集合的尾部
 29         var list4 = list2 ++ List("J","Q","K")
 30         print(s"list4=====> ${list4}
")
 31         //“++:”是将右边的集合的每一个元素元素放置在左边集合的头部哟
 32         var list5 = list2.++:(List("J","Q","K"))
 33         print(s"list5=====> ${list5}
")
 34         //“+:”是将右边的集合的放置在左边集合的头部,并非是将右边的集合的每个元素放进去!
 35         var list6 = list2.+:(List("J","Q","K"))
 36         print(s"list6=====> ${list6}
")
 37         //“:+”是将右边的集合的放置在左边集合的尾部部,并非是将右边的集合的每个元素放进去!
 38         var list7 = list2.:+(List("J","Q","K"))
 39         print(s"list7=====> ${list7}
")
 40         //“::”方法是将右边集合的每个元素和左边的集合合并为一个新的集合
 41         var list8 = list2::(List("J","Q","K"))
 42         print(s"list8=====> ${list8}
")
 43         //判断list9集合中存在偶数的个数
 44         val list9 = List(9,2,3,6,8,7,1,4,5)
 45         val  res1 = list9.count(x => x % 2 == 0)
 46         print(s"res1=====> ${res1}
")
 47         //判断list9集合中偶数的值
 48         val res2 = list9.filter(x => x % 2 == 0)
 49         print(s"res2=====> ${res2}
")
 50         //对list9进行升序排序
 51         val  res3 = list9.sorted
 52         print(s"res3=====> ${res3}
")
 53         //list9进行降序排序,如果我们不用负号("-"),那么默认是以升序排序
 54         val res4 = list9.sortBy(x => -x)
 55         print(s"res4=====> ${res4}
")
 56         //根据wordCount中的Int类型进行排序
 57         val wordCount = List(("yinzhengjie",100),("Scala",80))
 58         val res5 = wordCount.sortWith((x,y) => x._2 > y._2)
 59         print(s"res5=====> ${res5}
")
 60         //指定每个分组允许的最大个数
 61         val  lis10 = List("yinzhengjie","Shell","Python","VBS","HTML","CSS","JavaScript","Golang","Java","Scala")
 62         val res6 = lis10.grouped(3)
 63         res6.foreach(x => print(x  + "	"))
 64         print(s"res6=====> ${res6}
")
 65         /**
 66           * 注意fold(定义初始值)(叠加的函数)
 67           *     分析:val  res7 = list11.fold(0)(_+_)
 68           *     fold(0)中的初始值为 : 0
 69           *     (_+_)是叠加的函数,左边的下划线是初始值,右边的下划线是list11中的每一个元素
 70           *     综上所述:
 71           *         list11.fold(0)(_+_)会进行三次运算,因为list11的长度为3.
 72           *         第一次运算,计算结果为: (0+9)
 73           *         第二次运算的初始值是第一次计算的结果,计算结果为: (9+2)
 74           *         第三次运算的初始值是上一次计算的结果,计算结果为: (11+3)
 75           *         因此,我们可以得到最终的结果应该为: 14
 76           */
 77         val list11= List(9,2,3)
 78         val  res7 = list11.fold(0)(_+_)         //其实我们也可以这样写:val  res7 = list11.fold(0)((x,y) => x + y)
 79         print(s"res7=====> ${res7}
")
 80         /**
 81           * 相信你理解了上面的fold的方法,那么下面的fold的方法你估计也再熟悉不过了,因为fold底层调用的就是foldLeft方法。
 82           */
 83         var res8 = list11.foldLeft(0)(_+_)
 84         var res9 = list11.foldLeft(0)(_-_)
 85         print(s"res8=====> ${res8}
")
 86         print(s"res9=====> ${res9}
")
 87         /**
 88           * 在你理解foldLeft的工作原理后,相信foldRight对你来说更是小菜一碟啦,因为foldLeft和fold都是从左往右计算
 89           *     第一次运算,计算结果为: (9-0)
 90           *     第二次运算的初始值是上一次计算的结果,计算结果为: (2-9)
 91           *     第三次运算的初始值是上一次计算的结果,计算结果为: (3-(2-9))
 92           *     因此,我们可以得到最终的结果应该为: 10
 93           */
 94         var res10 = list11.foldRight(0)(_-_)
 95         print(s"res10=====> ${res10}
")
 96         //反转list的值,使用reverse方法
 97         var list12 = List("yinzhengjie","Shell","Python","Scala")
 98         list12 = list12.reverse
 99         print(s"list12=====> ${list12}
")
100         //将列表进行聚合操作,如果列表中有字符串就直接拼接,如果全部是int类型就累加操作
101         val res11 = list12.reduce((x,y) => x + y)
102         print(s"res11=====> ${res11}
")
103         //aggregate(在Spark已经把它封装为reduceByKey)可以模拟并行化集合,可以把集合打散,在非并行化底层还是调用的foldLeft
104         var res12 = list11.aggregate(0)(_ + _,_+_)
105         print(s"res12=====> ${res12}
")
106         //计算出两个集合中的并集,就可以调用union方法
107         var list13 = List(1,3,5,7,9,0,8)
108         var list14 = List(8,0,7,2,4,6)
109         var res13 = list13.union(list14)
110         print(s"res13=====> ${res13}
")
111         //计算交集,调用intersect方法即可
112         var res14 = list13.intersect(list14)
113         print(s"res14=====> ${res14}
")
114         //计算两个集合的差集,即可以理解为不同元素
115         var res15 = list13.diff(list14)
116         print(s"res15=====> ${res15}
")
117         //拉链函数,可以把两个元素集合的没有索引进行咬合,新城一个新的元组。如果一个集合中比另一个集合元素要少,那么会以较少元素个数的集合进行匹配。
118         var res16 = list13.zip(list14)
119         print(s"res16=====> ${res16}
")
120         //格式化字符串操作,比如以“|”将list13中的每个元素隔开,并将结果以字符串的形式返回
121         var res17 = list13.mkString("|")
122         print(s"res17=====> ${res17}
")
123         //计算集合的大小或者是长度
124         var res18 = list13.size
125         var res19 = list13.length
126         print(s"res18=====> ${res18}
")
127         print(s"res19=====> ${res19}
")
128         //对应list取切片操作,和Python语法有点像,同样也是挂前不顾后!
129         var list15 =List("yinzhengjie","Hadoop","Nginx","MySQL","TomCat","Httpd")
130         var res20 = list15.slice(1,3)
131         print(s"res20=====> ${res20}
")
132         //对一个Int类型的结合进行求和运算
133         var list16 = List(1,2,3,4,5,6,7,8,9,10)
134         var res21 = list16.sum
135         print(s"res21=====> ${res21}
")
136     }
137 }
138 
139 
140 /*
141 以上代码执行结果如下:
142 list.head=====> yinzhengjie
143 list.tail=====> List(Python, Golang, Java, Scala)
144 list=====> List()
145 list2=====>List(100, 200, 300)
146 list3=====> List(100, 200, 300)666666
147 list4=====> List(100, 200, 300, J, Q, K)
148 list5=====> List(J, Q, K, 100, 200, 300)
149 list6=====> List(List(J, Q, K), 100, 200, 300)
150 list7=====> List(100, 200, 300, List(J, Q, K))
151 list8=====> List(List(100, 200, 300), J, Q, K)
152 res1=====> 4
153 res2=====> List(2, 6, 8, 4)
154 res3=====> List(1, 2, 3, 4, 5, 6, 7, 8, 9)
155 res4=====> List(9, 8, 7, 6, 5, 4, 3, 2, 1)
156 res5=====> List((yinzhengjie,100), (Scala,80))
157 List(yinzhengjie, Shell, Python)    List(VBS, HTML, CSS)    List(JavaScript, Golang, Java)    List(Scala)    res6=====> empty iterator
158 res7=====> 14
159 res8=====> 14
160 res9=====> -14
161 res10=====> 10
162 list12=====> List(Scala, Python, Shell, yinzhengjie)
163 res11=====> ScalaPythonShellyinzhengjie
164 res12=====> 14
165 res13=====> List(1, 3, 5, 7, 9, 0, 8, 8, 0, 7, 2, 4, 6)
166 res14=====> List(7, 0, 8)
167 res15=====> List(1, 3, 5, 9)
168 res16=====> List((1,8), (3,0), (5,7), (7,2), (9,4), (0,6))
169 res17=====> 1|3|5|7|9|0|8
170 res18=====> 7
171 res19=====> 7
172 res20=====> List(Hadoop, Nginx)
173 res21=====> 55
174  */

2>.可变的序列 import scala.collection.mutable._

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 
 7 package cn.org.yinzhengjie.function
 8 
 9 import scala.collection.mutable.ListBuffer
10 
11 object ListOperationDemo {
12 
13     def main(args: Array[String]): Unit = {
14         //构建一个可变列表,初始有 3 个元素 1,2,3
15         val res = ListBuffer[Int](1,2,3)
16         print(s"res=====> ${res}
")
17 
18         //创建一个空的可变列表
19         val res2 =  new ListBuffer[Int]
20         print(s"res2=====> ${res2}
")
21 
22         //向 res2 中追加元素,注意:没有生成新的集合
23         res2+= 4
24         res2.append(5)
25         print(s"res2=====> ${res2}
")
26 
27         //将 res2 中的元素追加到 res 中, 注意:没有生成新的集合
28         res ++= res2
29         print(s"res=====> ${res}
")
30 
31         //将 res 和 res2 合并成一个新的 ListBuffer 注意:生成了一个集合
32         val res3 = res ++ res2
33         print(s"res3=====> ${res3}
")
34 
35         //将元素追加到 res 的后面生成一个新的集合
36         val res4 = res :+ 10
37         print(s"res4=====> ${res4}
")
38     }
39 }
40 
41 
42 
43 
44 /*
45 以上代码执行结果如下 :
46 res=====> ListBuffer(1, 2, 3)
47 res2=====> ListBuffer()
48 res2=====> ListBuffer(4, 5)
49 res=====> ListBuffer(1, 2, 3, 4, 5)
50 res3=====> ListBuffer(1, 2, 3, 4, 5, 4, 5)
51 res4=====> ListBuffer(1, 2, 3, 4, 5, 10)
52  */

二.Set集合

1>.不可变的 Set

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.function
 7 
 8 
 9 object setOperationDemo {
10     def main(args: Array[String]): Unit = {
11         var s1 =Set(1,2,3,5)
12         var s2 =Set(2,3,4)
13         //计算交集
14         val res1 = s1.intersect(s2)
15         val res2 = s1 & s2
16         println(s"res1 ======> ${res1}")
17         println(s"res2 ======> ${res2}")
18         //计算并集
19         val res3 = s1.union(s2)
20         val res4 = s1 | s2
21         println(s"res3 ======> ${res3}")
22         println(s"res4 ======> ${res4}")
23         //计算差集
24         val res5 = s1.diff(s2)
25         val res6 = s1 &~ s2
26         println(s"res5 ======> ${res5}")
27         println(s"res6 ======> ${res6}")
28 
29         /**
30           * 查看当前使用的是哪个类
31           */
32         println(s1.getClass)
33     }
34 }
35 
36 
37 
38 /*
39 以上代码执行结果如下 :
40 res1 ======> Set(2, 3)
41 res2 ======> Set(2, 3)
42 res3 ======> Set(5, 1, 2, 3, 4)
43 res4 ======> Set(5, 1, 2, 3, 4)
44 res5 ======> Set(1, 5)
45 res6 ======> Set(1, 5)
46 class scala.collection.immutable.Set$Set4
47  */

2>.可变的 Set

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.function
 7 
 8 import scala.collection.mutable
 9 
10 object setOperationDemo {
11     def main(args: Array[String]): Unit = {
12         /**
13           * 创建一个可变的 HashSet
14           */
15         val set1 =  new mutable.HashSet[Int]()
16         print(s"set1=====> ${set1}
")
17         /**
18           * 向“HashSet ”中添加元素 :
19           *     1>.由于set的顺序是无序的,因此插入过程中可能不存在 ;
20           *     2>.add一般用于追加一个元素 ;
21           *     3>.如果想要一次性追加多个元素可以用".+="的方式添加,也可以使用“++=”操作符 ;
22           */
23         set1.add(4)
24         set1 += (100,500)
25         set1.+=(300,200)
26         set1 ++= Set (1,3,5)
27         print(s"set1=====> ${set1}
")
28 
29         /**
30           * 向“HashSet”中删除元素 :
31           *     1>.删除一个元素一般用"remove"方法 ;
32           *     2>.如果要删除多个元素
33           */
34         set1 -= (100,200)
35         set1.-=(3,4)
36         set1.remove(5)
37         print(s"set1=====> ${set1}
")
38 
39         /**
40           * 查看当前使用的是那个类
41           */
42         println (set1.getClass)
43     }
44 }
45 
46 
47 
48 /*
49 以上代码执行结果如下 :
50 set1=====> Set()
51 set1=====> Set(1, 300, 100, 5, 3, 500, 4, 200)
52 set1=====> Set(1, 300, 500)
53 class scala.collection.mutable.HashSet
54  */

三.Map映射

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.basicGrammar
 7 
 8 import scala.collection.mutable
 9 
10 object MapDemo {
11     def main(args: Array[String]): Unit = {
12         //定义不可变的map
13         val map = Map[String,Int]("尹正杰" -> 18)
14         print(s"map=====> ${map}
")
15 
16         //定义一个可变的map
17         val changeableMap = mutable.HashMap[String,Int]()
18         print(s"changeableMap=====> ${changeableMap}
")
19 
20         //往可变map中添加元素,这种添加方式和Java如出一辙
21         changeableMap.put("尹正杰", 26 )
22         changeableMap += "yinzhengjie" -> 18                    //当然Scala也可以使用“+=”添加元素哟
23         changeableMap +=(("JDK",8),("Scala",2),("Hadoop",2))    //如果想要一次性添加多个元素,每个元素有逗号分隔即可
24         print(s"changeableMap=====> ${changeableMap}
")
25 
26         //删除map中元素
27         changeableMap.remove("Scala")
28         print(s"changeableMap=====> ${changeableMap}
")
29         changeableMap.-=("Hadoop")                              //当然Scala也可以使用“-=”删除元素哟
30         print(s"changeableMap=====> ${changeableMap}
")
31 
32         //获取Map中的元素
33         val  res1 = map.get("尹正杰").get
34         print(s"res1=====> ${res1}
")
35         val res2 = changeableMap.get("尹正杰").get
36         print(s"res2=====> ${res2}
")
37 
38         //getOrElse方法是判断Map中是否有某个key,如果有就返回具体的值,若没有则返回我们提前设定的值
39        val res3 = changeableMap.getOrElse("Python",100)
40        val res4 = changeableMap.getOrElse("JDK",200)
41         print(s"res3=====> ${res3}
")
42         print(s"res4=====> ${res4}
")
43 
44         /**
45           * 扩充知识点:
46           *     在Scala 中Option 类型样例类用来表示可能存在或也可能不存在的值(Option 的子类有Some
47           * 和None)。Some 包装了某个值,None 表示没有值。
48           *         Option 是Some 和None 的父类
49           *         Some 代表有(多例),样例类
50           *         None 代表没有(单例),样例对象
51           */
52         var res5:Option[Any] = Some("yinzhengjie","python","shell","vbs")
53         print(s"res5=====> ${res5}
")
54         //取出Option的值
55         val  res6 = res5.get
56         print(s"res6=====> ${res6}
")
57         //判断Option是否为空
58         val  res7 = res5.isEmpty
59         print(s"res7=====> ${res7}
")
60 
61         /**
62           *    Option 的get方法返回的为Option, 也就意味着res6可能取到也有可能没取到,如果res5=None 时,
63           * 会出现异常情况:  NoSuchElementException: None.get
64           */
65         res5=None
66         val res8 = res5.isEmpty
67         print(s"res8=====> ${res8}
")
68 //        val res9 = res5.get
69 //        print(s"res9=====> ${res9}
")
70     }
71 }
72 
73 
74 
75 /*
76 以上代码执行结果如下 :
77 map=====> Map(尹正杰 -> 18)
78 changeableMap=====> Map()
79 changeableMap=====> Map(yinzhengjie -> 18, Hadoop -> 2, 尹正杰 -> 26, Scala -> 2, JDK -> 8)
80 changeableMap=====> Map(yinzhengjie -> 18, Hadoop -> 2, 尹正杰 -> 26, JDK -> 8)
81 changeableMap=====> Map(yinzhengjie -> 18, 尹正杰 -> 26, JDK -> 8)
82 res1=====> 18
83 res2=====> 26
84 res3=====> 100
85 res4=====> 8
86 res5=====> Some((yinzhengjie,python,shell,vbs))
87 res6=====> (yinzhengjie,python,shell,vbs)
88 res7=====> false
89 res8=====> true
90  */

四.元组(Tuple

  Scala 元组将固定数量的项目组合在一起,以便它们可以作为一个整体传递。与数组或列表不同,元组可以容纳不同类型的对象,但它们也是不可变的。元组是类型Tuple1,Tuple2,Tuple3 等等。目前在Scala 中只能有22 个上限,如果您需要更多个元素,那么可以使用集合而不是元组。

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.basicGrammar
 7 
 8 object TupleDemo {
 9 
10     def main(args: Array[String]): Unit = {
11 
12         //定义一个元组
13         val tuple = ("yinzhengjie",2018,true,Unit)
14 
15         //访问元素中的第一个元素,根据下标访问即可,默认是从1开始计数的
16         val res1 = tuple._1
17         print(s"res1=====> ${res1}
")
18 
19         /**
20           * productIterator:
21           *     可以将一个元组转换成一个数组
22           * foreach:
23           *     可以遍历迭代器中的每一个元素
24           */
25         tuple.productIterator.foreach(x => print(x + "	"))
26         println()
27 
28         /**
29           * 对偶元组:
30           *     顾名思义。对偶元组指的是元组中元素的个数只有2个。
31           */
32         val tuple1 = ("yinzhengjie",2018)
33         print(s"tuple1=====> ${tuple1}
")
34         val res2 = tuple1.swap
35         print(s"res2=====> ${res2}
")
36 
37     }
38 
39 }
40 
41 
42 
43 /*
44 以上代码执行结果如下:
45 res1=====> yinzhengjie
46 yinzhengjie    2018    true    object scala.Unit    
47 tuple1=====> (yinzhengjie,2018)
48 res2=====> (2018,yinzhengjie)
49  */

五.Scala中的并行化集合

  Scala结合Hadoop中的MapReduce思想,可以模拟分布式计算,使用par方法即可。
 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.function
 7 
 8 object MyListPar {
 9     def main(args: Array[String]): Unit = {
10         var list = (1 to 10).toList
11         println(list)
12 
13         /**
14           * 在没有开启并行化时,我们会看到执行map任务时都在主线程执行
15           */
16         list.map(e => {
17             //获取当前线程名称
18             val name = Thread.currentThread().getName()
19             println(name + " : " + e)
20             //将listl列表中的数据乘以2
21             println(e * 2)
22         })
23 
24         println("
==============我是分割线=============
")
25 
26         /**
27           * Scala结合Hadoop中的MapReduce思想,可以模拟分布式计算,使用par方法即可。
28           *     使用par方法将list对象转成并行化集合,我们会看到执行map任务时开启了多个线程执行,缺点是执行顺序不一致啦!
29           */
30         list.par.map(e => {
31             //获取当前线程名称
32             val name = Thread.currentThread().getName()
33             println(name + " : " + e)
34             //将listl列表中的数据乘以2
35             println(e * 2)
36         })
37     }
38 }
39 
40 
41 
42 /*
43 以上代码执行结果如下 :
44 List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
45 main : 1
46 2
47 main : 2
48 4
49 main : 3
50 6
51 main : 4
52 8
53 main : 5
54 10
55 main : 6
56 12
57 main : 7
58 14
59 main : 8
60 16
61 main : 9
62 18
63 main : 10
64 20
65 
66 ==============我是分割线=============
67 
68 scala-execution-context-global-11 : 1
69 2
70 scala-execution-context-global-11 : 2
71 4
72 scala-execution-context-global-14 : 8
73 scala-execution-context-global-12 : 6
74 12
75 scala-execution-context-global-12 : 7
76 14
77 scala-execution-context-global-13 : 3
78 6
79 scala-execution-context-global-13 : 4
80 8
81 scala-execution-context-global-13 : 5
82 10
83 16
84 scala-execution-context-global-14 : 9
85 18
86 scala-execution-context-global-14 : 10
87 20
88 
89  */

六.小试牛刀

1>.对数组的字符串进行单词统计

   不知道你是否感觉到了,大数据统计不管是MapReduce还是Spark他们最终的计算都类似于之中WordCount,因此想要学习大数据,练习写WordCount是你必经之路,我们可以对一个数组的数据进行单词统计,以及排序等操作,只需要一行就可以搞定,而且速度那是相当的快呀!下面我介绍4中单词统计的方式,其实万变不离其宗。具体代码如下:

 1 /*
 2 @author :yinzhengjie
 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Scala%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 4 EMAIL:y1053419035@qq.com
 5 */
 6 package cn.org.yinzhengjie.basicGrammar
 7 
 8 object WordCount {
 9 
10     def main(args: Array[String]): Unit = {
11         //定义需要统计的单词
12         val words = Array("hello Scala","hello Spark","hello Java","Java Scala")
13 
14         // 实现方式一
15         val res1 = words .flatMap(_.split(" "))                // 对数组中的每个元素进行切分, 并进行扁平化操作
16             .map((_, 1))                                       // 将数组的每个元素转换成一个对偶元组, 元组的第二个元素为1
17             .groupBy(_._1)                                     // 对集合中的所有元素进行按单词分组, 相同单词的元组分到一组
18             .mapValues(_.length)                               // 对每个key 的value 集合进行求长度操作
19             .toList                                            // 将map 转换成List
20             .sortBy(t => - t._2)                               // 实现降序排列,默认是升序排列
21 
22         // 实现方式二
23         val res2 = words .flatMap(_.split(" ")).groupBy(x => x).map(t => (t._1,t._2.length)).toList.sortBy(t => t._2)
24 
25         //实现方式三
26         val res3 = words.flatMap(_.split(" ")).map(x =>(x,1)).groupBy(x=>x._1).mapValues(t=>t.foldLeft(0)(_+_._2))
27 
28         //实现方式四
29         val res4 = words.flatMap(_.split(" ")).map(x =>(x,1)).groupBy(x =>x._1).mapValues(t=>t.foldRight(0)(_._2 + _)).toList.sortBy(t => - t._2)
30 
31         print(s"res1=====> ${res1}
")
32         print(s"res2=====> ${res2}
")
33         print(s"res3=====> ${res3}
")
34         print(s"res4=====> ${res4}
")
35 
36     }
37 }
38 
39 
40 
41 /*
42 以上代码执行结果如下:
43 res1=====> List((hello,3), (Scala,2), (Java,2), (Spark,1))
44 res2=====> List((Spark,1), (Scala,2), (Java,2), (hello,3))
45 res3=====> Map(Spark -> 1, Scala -> 2, Java -> 2, hello -> 3)
46 res4=====> List((hello,3), (Scala,2), (Java,2), (Spark,1))
47  */

2>.