大家好,我是楚生辉,在未来的日子里我们一起来学习Scala相关的技术,一起努力奋斗,遇见更好的自己!
Scala是一门多范式的编程语言,一种类似java的编程语言,设计初衷是实现可伸缩的语言 、并集成面向对象编程和函数式编程的各种特性。今天着重分享一下集合常用函数相关知识,有需要的小伙伴可以自行获取与学习~
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 set里面没有lenth
println(list.size)
//(3)循环遍历
list.foreach(println)
//(4)迭代器
for (elem <- list.itera tor) {
println(elem)
}
//(5)生成字符串,自定义--分隔符
println(list.mkString("--"))
//(6)判断是否包含某个元素
println(list.contains(3))
}
}
调用这些方法,可以生成新的集合
object TestList {
def main(args: Array[String]): Unit = {
val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
val list2: List[Int] = List(4, 5, 6, 7, 8, 9, 10)
//(1)获取集合的头
println(list1.head)
//(2)获取集合的尾(去掉头,剩下的都是尾)
println(list1.tail)
//(3)集合最后一个数据
println(list1.last)
//(4)集合初始数据(去掉最后一个,前面都叫初始数据)
println(list1.init)
//(5)反转
println(list1.reverse)
//(6)取前(后)n 个元素
println(list1.take(3))
println(list1.takeRight(3))
//(7)去掉前(后)n 个元素
println(list1.drop(3))
println(list1.dropRight(3))
//(8)并集
println(list1.union(list2))
//(9)交集
println(list1.intersect(list2))
//(10)差集
println(list1.diff(list2))
//(11)拉链 注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
println(list1.zip(list2))
// List((1,4), (2,5), (3,6), (4,7), (5,8), (6,9), (7,10))
//(12)滑窗
list1.sliding(3).foreach(println) // 3个数一个窗口,步进默认是1
list1.sliding(2, 5).foreach(println) // 2个数一个窗口,步进为5
// List(1, 2, 3)
// List(2, 3, 4)
// List(3, 4, 5)
// List(4, 5, 6)
// List(5, 6, 7)
// List(1, 2)
// List(6, 7)
}
}
如果集合里面的内容是元组类型,那么默认比较第一个的Ascii码值,如果我们需要比较指定排序的元素,我们就需要定义函数
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)排序
// 从小到大排序
println(list.sorted)
// 从大到小排序
println(list.sorted.reverse)
// 按照元素大小排序
println(list.sortBy(x => x))
// 按照第二个数据进行从小到大排序
println(list.sortBy( _._2))
// 按照元素的绝对值大小排序
println(list.sortBy(x => x.abs))
// 按元素大小升序排序 <就是从小到大, >就是从大到小
println(list.sortWith( (x:Int, y:Int) => {x < y} ))
println(list.sortWith( _ < _ ))
// 按元素大小降序排序
println(list.sortWith((x, y) => x > y))
println(list.sortWith( _ > _ ))
}
}
sorted :对一个集合进行自然排序,通过传递隐式的 Ordering
sortBy : 对一个属性或多个属性进行排序,通过它的类型。
sortWith :基于函数的排序,通过一个 comparator 函数,实现自定义排序的逻辑。
object Test05_Extents {
def main(args: Array[String]): Unit = {
val list= List(("a",3),("b",2),("c",8),("d",1),("e",4))
// 根据元组的第二个数进行筛选出最大值
println(list.maxBy((tuple:(String,Int))=> tuple._2 ))
// 简写
println(list.maxBy( _._2 ))
}
}
// 输出
(c,8)
(c,8)
说明
过滤:遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
转化/映射(map):将集合中的每一个元素映射到某一个函数
扁平化 : 拆成每一个具体的元素再整合到一个集合 多用于集合嵌套
扁平化+映射
注:flatMap 相当于先进行 map 操作,在进行 flatten 操作集合中的每个元素的子元素映射到某个函数并返回新集合
分组(group) : 按照指定的规则对集合的元素进行分组
简化(归约):所有的数据都保持一个状态进行叠加处理,返回值类型是Map类型
折叠:
实操
object TestList {
def main(args: Array[String]): Unit = {
val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val nestedList: List[List[Int]] = List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9))
val wordList: List[String] = List("hello world", "hello nantong", "hello scala")
//(1)过滤 选取数据是偶数的数据 是true就保留,是false就舍弃
println(list.filter( (x:int)=> {x % 2 == 0} ))
println(list.filter(_ % 2 == 0))
//(2)转化/映射
println(list.map(x => x + 1))
println(list.map(_ + 1))
//(3)扁平化
println(nestedList.flatten)
//(4)扁平化+映射 注:flatMap 相当于先进行 map 操作(进行分隔成数组),进行扁平化操作
println(wordList.flatMap(x => x.split(" ")))
println(wordList.flatMap(_.split(" ")))
//(5)分组 为true的分一组,对于2取余的结果当成组名然后分组 返回值类型是Map类型
println(list.groupBy(x => x % 2))
println(list.groupBy( _ % 2))
println(list.groupBy(x => if (x % 2== 0 ) "偶数" else "基数" ))
// Map(偶数 -> List(2, 4, 6, 8), 基数 -> List(1, 3, 5, 7, 9))
// 给定一组词汇,按照单词的首字母进行分组计算
val list = List("world", "nantong", "scala")
println(list.groupBy(_.charAt(0)))
}
}
Reduce 方法
Reduce 简化(归约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。
object TestReduce {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
// 将数据两两结合,实现运算规则
val i: Int = list.reduce( (x,y) => x-y )
println("i = " + i)
// 从源码的角度,reduce 底层调用的其实就是 reduceLeft
//val i1 = list.reduceLeft((x,y) => x-y)
// ((4-3)-2-1) = -2
val i2 = list.reduceRight((x,y) => x-y)
println(i2)
}
}
Fold 方法
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)
}
}
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
map
}
}
println(map3)
}
}
需求 单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
案例实操
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 Test05_Extents {
def main(args: Array[String]): Unit = {
val stringList = List("Hello Scala Hbase kafka", "Hello Scala Hbase", "Hello Scala", "Hello flink from Scala")
val wordList = stringList.flatMap(_.split(" "))
val groupMaps = wordList.groupBy(word => word)
println(groupMaps)
// 对分组之后的list取长度的,得到每个单词的个数
val countMap = groupMaps.map(kv => (kv._1,kv._2.length))
println(countMap)
// 将map转化为list并且排序取前三
val sortList:List[(String,Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)
println(sortList)
}
}
// 控制台打印
1.Map(Hbase -> List(Hbase, Hbase), Scala -> List(Scala, Scala, Scala, Scala), flink -> List(flink), kafka -> List(kafka), Hello -> List(Hello, Hello, Hello, Hello), from -> List(from))
2.Map(Hbase -> 2, Scala -> 4, flink -> 1, kafka -> 1, Hello -> 4, from -> 1)
3.List((Scala,4), (Hello,4), (Hbase,2))
存在一些预统计,里面还有一些已经统计好的数据
思路一:直接展开为普通版本,数字是几,就展开多少个
思路二:直接根据预先统计的结果去转换
object Test05_Extents {
def main(args: Array[String]): Unit = {
val tupleList: List[(String, Int)] = List(
("hello", 1),
("hello world", 2),
("hello scala", 3),
("hello spark from scala", 1),
("hello flink from Scala", 2),
)
// 思路一:根据后面的数字进行拆分,数字是几,就拆分成多少个
val newStringList = tupleList.map(
kv => {
(kv._1 + " ") * kv._2
}
)
val list: List[(String, Int)] = newStringList
.flatMap(_.split(" ")) // 空格分词
.groupBy(word => word) // 对单词分组
.map(kv => (kv._1, kv._2.length)) // 统计单词个数
.toList.sortWith(_._2 > _._2) //转化为集合并且排序
println(list)
// 思路二:直接基于预统计的结果进行转换。每一个单词都跟后面的数字进行一个元组
// 1. 将字符串打散为单词并且与后面的个数结合包装成元组
val preCountList: List[(String, Int)] = tupleList.flatMap(
tuple => {
val strings: Array[String] = tuple._1.split(" ")
strings.map(word => (word, tuple._2))
}
)
println(preCountList)
// List((hello,1), (hello,2), (world,2), (hello,3), (scala,3), (hello,1), (spark,1), (from,1), (scala,1), (hello,2), (flink,2), (from,2), (Scala,2))
// 2. 对二元组按照单词进行分组
val preCountMap = preCountList.groupBy(_._1)
println(preCountMap)
// 3. 叠加每个单词预统计的数值 只取map的value
val CountMap = preCountMap.mapValues(
// 取出List的第二个元素并且进行sum聚合相加
tupleList => tupleList.map(_._2).sum
)
val list1: List[(String, Int)] = CountMap.toList.sortWith(_._2>_._2)
println(list1)
}
}