集合常用函数
object TestCommonOp {
def main(args: Array[String]): Unit = {
val list = List(1, 3, 4, 5, 6, 7, 8, 99)
val set = Set(33, 45, 66, 77)
// (1)获取集合长度,线性的序列都可以获取到长度
println(list.length)
// (2)获取集合大小,几乎有集合类型都可以获取到大小
println(set.size)
// (3)循环遍历
for (elem <- list) {
println(elem)
}
set.foreach(println)
// (4)迭代器
for (elem <- list.iterator) {
println(elem)
}
// (5)生成字符串
println(list) // List(1, 3, 4, 5, 6, 7, 8, 99)
println(set) // Set(33, 45, 66, 77)
println(list.mkString("-")) // 1-3-4-5-6-7-8-99
// (6)是否包含
println(list.contains(1)) // true
println(set.contains(44)) // false
}
}
衍生集合
object TestDerivedCollection {
def main(args: Array[String]): Unit = {
val list = List(1, 3, 55, 66, 77)
val list2 = List(1, 44, 55, 88, 99)
// (1)获取集合的头,一般在有序的集合才用这个
println(list.head) // 1
// (2)获取集合的尾(不是头的就是尾)
println(list.tail) // List(3, 55, 66, 77)
// (3)集合最后一个数据
println(list.last) // 7
// (4)集合初始数据(不包含最后一个)
println(list.init) // List(1, 3, 55, 66)
// (5)反转
println(list.reverse) // List(77, 66, 55, 3, 1)
// (6)取前(后)n 个元素
// 取前3个元素
println(list.take(3)) // List(1, 3, 55)
// 取出后4个元素
println(list.takeRight(4)) // List(3, 55, 66, 77)
// (7)去掉前(后)n 个元素
// 取去掉前三个之后剩下的
println(list.drop(3)) // List(66, 77)
// 取去掉前二个之后剩下的
println(list.dropRight(2)) // List(1, 3, 55)
// (8)并集
println("union: " + list.union(list2)) // union: List(1, 3, 55, 66, 77, 1, 44, 55, 88, 99)
println(list ++ list2) // List(1, 3, 55, 66, 77, 1, 44, 55, 88, 99)
// Set并集
val set = Set(1, 3, 55, 66, 77)
val set2 = Set(1, 44, 55, 88, 99)
println("set union: " + set.union(set2)) // set union: Set(88, 1, 77, 44, 66, 3, 99, 55)
println(set ++ set2) // Set(88, 1, 77, 44, 66, 3, 99, 55)
// (9)交集
println("intersection: " + list.intersect(list2)) // intersection: List(1, 55)
// (10)差集,求集合独有的元素
val diff1 = list.diff(list2)
val diff2 = list2.diff(list)
println(s"diff1: $diff1") // diff1: List(3, 66, 77)
println(s"diff2: $diff2") // diff2: List(44, 88, 99)
// (11)拉链,两个集合中元素对应位置组合成为二元组,多出来的去掉
println("zip1: " + list.zip(list2)) // zip1: List((1,1), (3,44), (55,55), (66,88), (77,99))
println("zip2: " + list2.zip(list)) // zip2: List((1,1), (44,3), (55,55), (88,66), (99,77))
// (12)滑窗
// 得到大小为3的窗口大小,还可以传入步数,默认每次滑动1
for (elem <- list.sliding(3)) {
println(elem)
// List(1, 3, 55)
// List(3, 55, 66)
// List(55, 66, 77)
}
for (elem <- list.sliding(3, 2)) {
println(elem)
// List(1, 3, 55)
// List(55, 66, 77)
}
for (elem <- list.sliding(3, 3)) {
println(elem)
// 滑动完成之后,最后一个窗口数量不够也要写出来
// List(1, 3, 55)
// List(66, 77)
}
}
}
集合计算简单函数
object TestSimpleFunction {
def main(args: Array[String]): Unit = {
val list = List(1, 4, 55, 77, -33, -90)
val list2 = List(("a", 1), ("b", 4), ("c", 55), ("d", 77), ("e", -33), ("f", -90))
// (1)求和
var sum = 0
for (elem <- list) {
sum += elem
}
println(sum) // 14
println(list.sum) // 14
// (2)求乘积
println(list.product) // 50311800
// (3)最大值
println(list.max) // 77
println(list2.max) // (f,-90) 默认以二元组的第一个位置来比较
// 取二元组的第二个位置作为比较
println(list2.maxBy((tuple: (String, Int)) => tuple._2)) // (d,77)
// 简写
println(list2.maxBy(_._2)) // (d,77)
// (4)最小值
println(list.min) // -90
println(list2.minBy(_._2)) // (f,-90)
// (5)排序
// 5.1 sorted,默认从小到大
val sortedList1 = list.sorted
println(sortedList1) // List(-90, -33, 1, 4, 55, 77)
// 从大到小
// 这个做了两次操作
println(list.sorted.reverse) // List(77, 55, 4, 1, -33, -90)
// 一步到位
println(list.sorted(Ordering[Int].reverse)) // List(77, 55, 4, 1, -33, -90)
println(list2.sorted) // List((a,1), (b,4), (c,55), (d,77), (e,-33), (f,-90))
// 5.2 sortedBy
println(list2.sortBy(_._2)) // List((f,-90), (e,-33), (a,1), (b,4), (c,55), (d,77))
println(list2.sortBy(_._2)(Ordering[Int].reverse)) // List((d,77), (c,55), (b,4), (a,1), (e,-33), (f,-90))
// 5.3 sortWith,两个参数不用换位置则返回true,需要换位置则返回true
println(list.sortWith((a, b) => { a < b })) // List(-90, -33, 1, 4, 55, 77)
// 简写
println(list.sortWith(_ < _)) // List(-90, -33, 1, 4, 55, 77)
}
}
(1)sorted 对一个集合进行自然排序,通过传递隐式的 Ordering
(2)sortBy 对一个属性或多个属性进行排序,通过它的类型。
(3)sortWith 基于函数的排序,通过一个 comparator 函数,实现自定义排序的逻辑。
集合计算高级函数
(1)过滤 遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2)转化/映射(map) 将集合中的每一个元素映射到某一个函数
(3)扁平化 将集合中所有的集合打散组成一个新的集合
(4)扁平化+映射 注:flatMap 相当于先进行 map 操作,在进行 flatten 操作,集合中的每个元素的子元素映射到某个函数并返回新集合
(5)分组(group) 按照指定的规则对集合的元素进行分组,分组之后得到的是Map
(6)简化(归约) 通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。
(7)折叠
前五个是map操作,后两个是reduce操作,map操作主要是对集合进行转换,reduce是都集合进行汇总
map操作
object TestHighLevelFunctionMap {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// 1、过滤
// 选取偶数
val evenList = list.filter((elem: Int) => {
elem % 2 == 0
})
println(evenList) // List(2, 4, 6, 8)
// 选取奇数
println(list.filter(_ % 2 == 1)) // List(1, 3, 5, 7, 9)
// 2、map
// 把集合中每个数乘与2
println(list.map(_ * 2)) // List(2, 4, 6, 8, 10, 12, 14, 16, 18)
// 3、扁平化
val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5), List(6, 7, 8, 9))
val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
println(flatList) // List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val flatList2 = nestedList.flatten
println(flatList2) // List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// 4、扁平映射
// 将一组字符串进行分词,并保存成分词的列表
val strs: List[String] = List("hello word", "hello scala", "hello java", "i study")
val splitList: List[Array[String]] = strs.map(_.split(" ")) // 分词
val flattenList = splitList.flatten // 打散扁平化
println(flattenList) // List(hello, word, hello, scala, hello, java, i, study)
val flatmapList = strs.flatMap(_.split(" "))
println(flatmapList) // List(hello, word, hello, scala, hello, java, i, study)
// 5、分组groupBy
// 分成奇数和偶数组
val groupMap: Map[Int, List[Int]] = list.groupBy(_ % 2)
val groupMap2: Map[String, List[Int]] = list.groupBy(data => {if (data % 2 == 0) "偶数" else "奇数"})
println(groupMap) // Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
println(groupMap2) // Map(奇数 -> List(1, 3, 5, 7, 9), 偶数 -> List(2, 4, 6, 8))
// 给定一组词汇,按照单词的首字母进行分组
val wordList = List("china", "caocao", "liubei", "sunquan")
println(wordList.groupBy(_.charAt(0))) // Map(s -> List(sunquan), l -> List(liubei), c -> List(china, caocao))
}
}
reduce操作,
object TestHighLevelFunctionReduce {
def main(args: Array[String]): Unit = {
val list = List(1, 2, 3, 4)
// 1、reduce,归约
println(list.reduce(_ + _)) // 10,默认就是reduceLeft
println(list.reduceLeft(_ + _)) // 10,从左往右加
println(list.reduceRight(_ + _)) // 10,从右往左加 1 + (2 + (3 + 4))
println(list.reduce(_ - _)) // -8
println(list.reduceLeft(_ - _)) // -8,从左往右减
println(list.reduceRight(_ - _)) // -2,1 - (2 - (3 - 4))
// 2、fold 折叠
println(list.fold(10)(_ + _)) // 20,10 + 1 + 2 + 3 + 4
println(list.foldLeft(10)(_ - _)) // 0,10 - 1 - 2 - 3 - 4
println(list.foldRight(10)(_ - _)) // 8,1 - (2 - (3 - (4 - 10)))
}
}
mergeMap的操作
object TestMergeMap {
def main(args: Array[String]): Unit = {
val map1 = Map("a" -> 1, "b" -> 2, "c" -> 3, "e" -> 8)
val map2 = mutable.Map("a" -> 5, "b" -> 6, "c" -> 7, "d" -> 9)
val map3 = map1.foldLeft(map2)(
(mergedMap, kv) => {
val key = kv._1
val value = kv._2
mergedMap(key) = mergedMap.getOrElse(key, 0) + value
mergedMap
}
)
println(map3) // Map(e -> 8, b -> 8, d -> 9, a -> 6, c -> 10)
}
}
普通 WordCount 案例
需求:单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
分析
object TestCommonWordCount {
def main(args: Array[String]): Unit = {
val stringList = List(
"hello caocao",
"hello liubei",
"hello sunquan",
"caocao is a shuaige",
"liubei ye shi shuaige",
"sunquan de gege shi shuaige",
"caocao lihai"
)
// 1、对字符串进行切分,得到一个打散所有单词的列表
// val wordList = stringList.map(_.split(" "))
// val wordList2 = wordList.flatten
val wordList = stringList.flatMap(_.split(" "))
println(wordList)
// List(hello, caocao, hello, liubei, hello, sunquan, caocao, is, a, shuaige, liubei, ye, shi, shuaige, sunquan, de, gege, shi, shuaige, caocao, lihai)
// 2、相同单词进行分组
val groupMap = wordList.groupBy(word => word)
println(groupMap)
// Map(is -> List(is), lihai -> List(lihai), ye -> List(ye), a -> List(a), de -> List(de), shi -> List(shi, shi), gege -> List(gege), caocao -> List(caocao, caocao, caocao), liubei -> List(liubei, liubei), hello -> List(hello, hello, hello), sunquan -> List(sunquan, sunquan), shuaige -> List(shuaige, shuaige, shuaige))
// 3、对分组之后的list去长度,得到每个单词的个数
val countMap = groupMap.map(kv => kv._1 -> kv._2.length)
// 4、将map转换成list,并排序取前三
val sortList = countMap.toList.sortWith(_._2 > _._2)
println(sortList) // List((caocao,3), (hello,3), (shuaige,3), (shi,2), (liubei,2), (sunquan,2), (is,1), (lihai,1), (ye,1), (a,1), (de,1), (gege,1))
println(sortList.take(3)) // List((caocao,3), (hello,3), (shuaige,3))
}
}
复杂WordCount案例
object TestComplexWordCount {
def main(args: Array[String]): Unit = {
val stringList = List(
("hello caocao", 1),
("hello liubei", 2),
("hello sunquan", 3),
("caocao is a shuaige", 4),
("liubei ye shi shuaige", 5),
("sunquan de gege shi shuaige", 6),
("caocao lihai", 7)
)
// 思路一,直接展开为普通版本
val newStringList = stringList.map(
kv => {
(kv._1.trim + " ") * kv._2
}
)
println(newStringList)
// 接下来操作与普通版本完全相同
val wordCountList: List[(String, Int)] = newStringList
.flatMap(_.split(" ")) // 空格分词
.groupBy(word => word) // 单词分组
.map(kv => kv._1 -> kv._2.length) // 统计每个单词出现的个数
.toList
.sortWith(_._2 > _._2) // 排序
.take(3)
println(wordCountList) // List((shuaige,15), (caocao,12), (shi,11))
// 思路二:直接根据预统计的结果进行计算
val wordCountList2 = stringList
// 将字符串打散为单词,并结合对应的个数包装成二元组
.flatMap(tuple => {
val strings = tuple._1.split(" ")
strings.map(word => word -> tuple._2)
}) // List((hello,1), (caocao,1), (hello,2), (liubei,2), (hello,3), (sunquan,3), (caocao,4), (is,4), (a,4), (shuaige,4), (liubei,5), (ye,5), (shi,5), (shuaige,5), (sunquan,6), (de,6), (gege,6), (shi,6), (shuaige,6), (caocao,7), (lihai,7))
// 对二元组进行分组
.groupBy(kv => kv._1) // Map(is -> List((is,4)), lihai -> List((lihai,7)), ye -> List((ye,5)), a -> List((a,4)), de -> List((de,6)), shi -> List((shi,5), (shi,6)), gege -> List((gege,6)), caocao -> List((caocao,1), (caocao,4), (caocao,7)), liubei -> List((liubei,2), (liubei,5)), hello -> List((hello,1), (hello,2), (hello,3)), sunquan -> List((sunquan,3), (sunquan,6)), shuaige -> List((shuaige,4), (shuaige,5), (shuaige,6)))
// 叠加每个单词预统计的个数
.map(kv => kv._1 -> kv._2.map(_._2).sum)
.toList
.sortWith(_._2 > _._2) // 排序
.take(3)
println(wordCountList2) // List((shuaige,15), (caocao,12), (shi,11))
}
}