Scala 集合常用函数

集合常用函数

一、基本属性和常用操作

1、常用方法

(1) 获取集合长度
(2) 获取集合大小
(3) 循环遍历
(4) 迭代器
(5) 生成字符串
(6) 是否包含
注意这些是集合类型的通用操作

2、案例示例

总结:获取集合的长度使用lenght方法,对于线性的序列都可以用lenght方法来获取长度,但是像那种无序的集合,像Set集合,就不能用lenght方法,可以用size方法,来获取大小。遍历的话可以用for循环,获取迭代器。或者foreach方法都可以。生成字符串,使用mkstring()方法,这个方法非常好用。判断这个元素在集合中是否包含,使用contains()方法,如果存在返回true,如果不存在返回false

package Scala03_shujujiegou
//这些是集合类型的通用的一些常用操作
class test11_tongyong {

}
object test11_tongyong{
  def main(args: Array[String]): Unit = {
    val list = List(6,9,6,89,99) //熟悉的列表
    val set = Set(6,8,6,1) //Set集合,不关心这个有多长因为他根本是无序的,所以关心的是他的大小
      //(1) 获取集合长度
    println(list.length) //获取长度length方法,只要是线性的序列都可以用lenght方法,如果是那种无序的可以用size
    //println(set.lenght) //对于某一些类型而言是没有lenght这个属性的,比如Set集合
    println(set.size) //对于无序的用大小比较合适,
    println("================")
      //(2) 获取集合大小
    println(list.size) //获取大小size方法
      //(3) 循环遍历
    for (i <- list){
      println(i)
    }
    for (i <- 0 until list.length){
      println(list(i))
    }

    println("============")
      //(4) 迭代器
    val iter = list.iterator //while循环的迭代器
    while (iter.hasNext){
      println(iter.next())
    }
    for (i <- list.iterator){ //for循环的迭代器
      println(i)
    }
    


      //(5) 生成字符串
    println(list.mkString(",")) //用字符串连接在一起mkString方法
      //(6) 是否包含
    println(list.contains(6)) //判断这个元素是否存在,contains方法。如果存在返回true,不存在返回false
  }
}

二、衍生集合

1、衍生集合常用方法操作

说明
(1) 获取集合的头
(2) 获取集合的尾 (不是头的都是尾)
(3) 集合最后一个数据
(4) 集合初始数据 (不包含最后一个)
(5) 反转集合
(6) 取前(后) n 个元素
(7) 去掉前(后) n 个元素
(8) 交集
(9) 并集
(10) 差集
(11) 拉链
(12) 滑窗

2、案例示例

总结:大概分两种,一个集合的操作,和两个集合的操作
一个集合
获取集合的头使用head方法,也就是集合的第一个元素。获取集合的尾,使用tail方法,注意除了头其他的元素都是尾。获取集合的最后一个元素,使用last方法。获取集合的初始数据,使用init方法,注意除了集合的最后一个元素,其他的元素都是初始数据。反转集合,使用reverse方法,这个方法很常用。取集合的前几个元素或者后几个元素,使用take()方法,里面的参数是取几个,取后几个元素用takeRight方法,相当于从后面开始取,但是输出来的元素的顺序还是没变的。去掉前几个元素或者后面几个元素,使用drop()方法,里面的参数是去掉几个元素,去掉后面几个元素使用dropRight()方法。
两个集合的操作
求两个集合的并集,使用union()方法,里面的参数是要求并集的集合,注意如果是Set集合做并集的操作的话,那么会自动去重。两个集合的交集使用intersect()方法。求两个集合的差集使用diff()方法,里面的参数第二个集合,差集的意思是就是前面那个集合有的,第二个集合没有的元素,称之为差集。求两个集合的拉链,使用zip方法,两个集合的拉链的意思是两个集合中的元素一一对应,然后返回一个二元组的形式。求集合的滑窗,这个是一个集合的操作,使用sliding()方法,里面的参数是要每一个滑窗的元素个数,滑窗的意思是第一次输出123个元素,第二次输出的是234,这样依次滑下称之为滑窗,要是里面有两个参数的话,那么第二个参数就是步长

package Scala03_shujujiegou
//衍生集合方法
class test12_yansheng {

}
object test12_yansheng{
  def main(args: Array[String]): Unit = {
    val list = List(6,12,33,45,56)
    val list2 = List(32,65,45,46,321)
  //    (1) 获取集合的头
    println(list.head) //获取集合的头使用head方法,可迭代的类型都可以用,一般在有序的类型里面有,无序的不考虑头和尾
  //    (2) 获取集合的尾 (不是头的都是尾)
    println(list.tail) //获取集合的尾用tail方法,注意除了头其他所有的元素都是尾
  //    (3) 集合最后一个数据
    println(list.last) //获取集合的最后一个元素使用last方法
  //    (4) 集合初始数据 (不包含最后一个)
    println(list.init) //init方法,除了最后一个元素,其他的元素都是初始数据
  //    (5) 反转集合
    println(list.reverse) //reverse方法,将集合给翻转过来
  //    (6) 取前(后) n 个元素
    println(list.take(3)) //取前几个元素用take方法
    println(list.takeRight(3)) //取后几个元素,用takeRight方法,从右边开始取,顺序是不变的
  //    (7) 去掉前(后) n 个元素
    println(list.drop(3)) //去掉前几个元素用drop方法
    println(list.dropRight(3)) //全掉后几个元素用dropRight方法

    //前面的都是一个集合做的操作,后面的时候基于两个集合做的操作

  //    (8) 并集
    println("==============")
    val union = list.union(list2) //求两个集合的并集也就是合在一起,使用union方法
    println("并集:"+union)
    println(list ::: list2) //获取使用 :::

    //如果是set做并集。那么重复的数据会被去重
    val set = Set(6,12,33,45,56)
    val set2 = Set(32,65,45,46,321,6)
    val union2 = set.union(set2)
    println(union2)
    println(set ++ set2)

    println("===============")
    //    (9) 交集
    val jiaoji = list.intersect(list2) //求两个集合的交集使用intersect方法
    println(jiaoji)

  //    (10) 差集
    val diff = list.diff(list2) //就是以前面那个表为基准,list里有的元素,list2里没有的元素就是差值
    println(diff)
    println("==============")
  //    (11) 拉链
    //这个拉链的意思是两个集合里的元素一一对应,返回一个一个的二元组
    println(list.zip(list2)) //两个集合的拉链使用zip方法,如果某一个集合多出来一个元素,那么就不显示那一个
  //    (12) 滑窗
    //滑窗的意思是,第一次取123元素,第二次去234,每次取三个这样滑下去,每次取多少可以定义
    println(list.sliding(3)) //滑窗使用sliding方法,里面的参数是每次滑的元素是几个,可以看到是一个迭代器
    for(i <- list.sliding(3)){ //使用类似于迭代器的方式遍历出来
      println(i)
    }
println("================")
    //要是里面有两个参数的话,第二个参数是步长,一个参数的时候默认步长是1
    for(i <- list.sliding(3,2)){
      println(i)
    }
  }
}

三、集合简单计算函数

1、常用计算操作

说明
(1) 求和
(2) 求乘积
(3) 最大值
(4) 最小值
(5) 排序

2、案例示例

总结
求集合的和使用sum方法,或者自己用增强for循环写,在外面定义一个变量初始值为0,然后进行累加。求集合里元素的乘积使用product方法。求集合里元素的最大值使用max方法。求集合里元素的最小值使用min方法。排序使用sorted方法,默认是升序,要是想降序的话,可以先排序,然后翻转列表,可以到达效果,
例如
println(list.sorted.reverse)
要是像是二元组什么的,默认是按照第一个参数排序,第一个参数是String类型的,第二个参数是Int类型的,要是想按照数字排序的话,那么就是用sortBy方法
例如println(list.sortBy(_._2))
还有第三种方法,sortWith这个方法相当于Java里面的比较器
例如println(list.sortWith((a,b) => {a<b}))如果a<b那么就不交换就是升序,可以简化为println(list.sortWith(_ < _))

package Scala03_shujujiegou
//集合常用简单计算函数
class test13_jiandanjisuan {

}
object test13_jiandanjisuan{
  def main(args: Array[String]): Unit = {
    val list:List[Int] = List(5,1,8,2,3,4)
    val list2 = List(("a",2),("c",1),("f,3"),("b",8))
  //    (1) 求和
    //自己用for循环写
    var sum = 0
    for (i <- list){
      sum += i //sum初始值为0,依次取出list列表里的值相加,最后结果不就是总和嘛
    }
    println("list的和为:"+sum)

    println(list.sum) //直接调用sum方法,直接就出来了
  //      (2) 求乘积
    println(list.product) //求成绩使用product方法
  //      (3) 最大值
    println(list.max) //求最大值使用max方法
  //      (4) 最小值
    println(list.min) //求最小值使用min方法
  //      (5) 排序
    //要做排序的话肯定是基于有序的集合类型才是有效的
    //1,sorted
    println(list.sorted) //这是升序,从小到大
    println(list.sorted.reverse) //哈哈降序可以先排序然后翻转列表,可以达到效果
    //传入隐式参数,降序排列 不传参数默认就是升序
    //println(list.sorted(Ordered[Int]))
    //2,sortBy
    //像那种二元组第一个值是String类的第二个类型是Int类型的,直接println(sortBy(_._2))就可以了,
    //3,sortWith 这个方法相当于java里的比较器
    println("================")
    println(list.sortWith((a,b) => {a<b}))  //a小于b的时候不用交换,如果a大于b就交换
    println(list.sortWith(_ < _ )) //可以直接简化成这个样子


  }
}

四、集合计算高级函数

1、语义说明

(1) 过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2) 转换/映射(map)
将集合中的每一个元素映射到某一个函数
(3) 扁平化 (flatten)
有点像两个列表要合并,列表里面还套着列表,我们要将他打散,这样的操作就叫做扁平化
(4) 扁平化+映射 注:flatMap相当于先进行map操作,再进行flatten操作集合中的每个元素的子元素映射到某个函数并返回新的集合
(5) 分组(group)
按照指定的规则对集合的元素进行分组,分组是转换成了map
(6) 简化(reduce归约)
这个有点像reduce
(7) 折叠(fold)

2、案例示例

总结
1、过滤使用filter()函数,里面的参数是一个函数,比如选取列表中的偶数可以写为:
val list2 = list1.filter(a => a % 2 == 0) 就可以将数组中所有的偶数筛选出来
在这里插入图片描述
2、映射使用map()函数,比如将集合中的每个数*2,可以写为:
println(list1.map(a => a * 2))
在这里插入图片描述
3、扁平化使用flatten函数,两个列表合并,列表中又嵌套了列表,将列表中的元素一个个拆开,然后合并成一个新的列表,比如:println(list1.flatten)
在这里插入图片描述
4、扁平映射,使用flatMap函数,就是先映射然后进行扁平化,就是将一组单词进行分词,然后保存成新的列表,比如:
println(list1.flatMap(a => a.spilt(" "))) //split函数使用空格分割单词,然后直接完成了映射扁平操作
在这里插入图片描述
5、分组使用groupBy()函数,里面的参数也是一个函数,比如列表里面有奇数和偶数:
println(list.groupBy(_ % 2)) 对2取余就只有两个结果一个是0,一个是1,然后就会自动分成两个组
再比如有一个需求,列表里都是单词,然后按照单词的首字母进行分组,首字母一样的都是一个组:
println(list.groupBy(a => a.charAT(0))) //charAt取单词的某个字母,参数是索引,然后就完成了单词的首字母的分组
在这里插入图片描述

package Scala03_shujujiegou
//集合高级计算函数
class test14_gaojijisuan {

}
object test14_gaojijisuan{
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4,5,6,7,8,9)
    //1、过滤
    //选取偶数
    val evenlist = list.filter(a => a % 2 == 0) //这里面传入的是一个函数
    val evenlist1 = list.filter(_ % 2 ==0 ) //可以简化成这样
    println(evenlist) //取余为0那么都是偶数
    println(evenlist1)

    //取奇数
    println(list.filter(_ % 2 == 1)) //可以直接不用赋值也可以

    //2、map
    //把集合中每个数乘2
    println(list.map(_ * 2)) //传入的参数也是一个函数
    println(list.map(a => a * a)) //这个是求平反方,这个就不能用_ * _了因为没有两个参数

    println("================")
    //3、扁平化
    //列表合并,将每一个列表拆成一个一个的元素,这种操作就是扁平化
    val list3:List[List[Int]] = List(List(1,2,3),List(4,5,6),List(6,7,8,9)) //这里这里面是list里面嵌套一个list
    val flatlist =list3(0) ::: list3(1) ::: list3(2) //先用索引吧每一个列表取出来,然后用:::合并在一起
    println(flatlist)

    //flatten ,上面那种方式要是数据非常的多那么就非常麻烦一个一个写出来,flatten方法一下就出来了
    val flatlist2 = list3.flatten //直接用flatten方法就完成了扁平化了
    println(flatlist2)

    println("=================")
    //4、扁平映射
    //将一组字符串进行分词,并保存成单词的列表
    //split方法是java里面的,包装在scala里面就是Array[String]类型的一个数组。所以相当于用map函数进行了映射,将这个数组转化为List
    val strings: List[String] = List("hello","word","scala","hello scala","hello java","we study")
    val split:List[Array[String]] = strings.map(a => a.split(" ")) //使用split方法,空格拆分
    val flattenList = split.flatten //首先经过映射之后,再调用flatten方法进行扁平化处理
    println(flattenList)
    println(split.flatten)

    //有个更简单的操作,flatMap函数,直接包含了先映射再扁平的这两步操作
    val flatmapList = strings.flatMap(a => a.split(" "))//相当于直接进行了转换然后在传入spilt操作
    println(flatmapList)

    println("==============")
    //5、分组groupBy
    //直接列表有奇数和偶数,直接分成两组
    val groupMap = list.groupBy(_ % 2) //对2取余就只有两个结果嘛一个是0,一个是1,然后这两种结果分为两个组了
    val groupMap2 = list.groupBy(a => { //用上面那个就行了
      if(a % 2 ==0){
        println("偶数")
      }else{
        println("奇数")
      }
    })
    println(groupMap)
    println(groupMap2)

    //给定一组词汇,按照单词的首字母进行分组
    val wordList = List("china","aex","alice","canda","cary","bob","japan")
    println(wordList.groupBy(a => a.charAt(0))) //charAt方法取单词的首字母


  }
}

(6) 简化(reduce归约)
sum都是一个归约操作,里面参数是两个相同类型的,最后最后结果就是一个数字
例如:println(list.reduce((a,b) => a * b))
(7) 折叠(fold)
折叠操作和reduce是一样的,有一个初始值,
例如:println(list.fold(10)(_ + _)) //然后初始值在前面 10 + 然后后面列表里的数依次相加
注意:reduce和fold折叠的区别就在于,fold有初始值,reduce没有初始值
在这里插入图片描述

package Scala03_shujujiegou
//高级计算函数
class test14_gajijisuan2 {

}
object test14_gajijisuan2{
  def main(args: Array[String]): Unit = {
    //reduce 类
    val list = List(1,2,3,4,5,6,7,8,9)

    //1、reduce (规约)
    println(list.reduce((a,b) => a * b))//里面的参数是一个函数,其实sum就是一个规约操作,最后只剩下了一个数

    val list2 = List(3,4,5,8,10)
    println(list2.reduce(_ - _)) //默认是reduceLeft,跟reduceRight不一样
    println(list2.reduceRight(_ - _)) //他这个结果是一个尾递归底层是这样的3-(4-(5-(8-10))) 结果就是-6

    println("=======================")
    //2、fold(折叠)
    // 过程:10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
    println(list.fold(10)(_ + _)) //前面那个参数是初始值,后面那个参数是操作。比如数组加起来45然后加个10
    println(list.foldLeft(10)(_ - _)) //10 - 1 -2 -3 -4 -5 -6 -7 -8 -9
    println(list.foldRight(10)(_ - _)) // 1 -(2 -(3 -(4 -(5 -(6 -(7 -(8 -(9 -10))))))))) 先是 9 -10
  }
}

五、应用案例

应用案例(1)- 合并 Map

思路:两个map合并,使用一个foldLeft()方法,以其中一个map为初始值,基准,然后对第二个map里的每一个key,value进行遍历,使用getOrElse()方法判断key是否在为基准的那个map里面存在,如果不存在返回一个初始值0,就直接添加进去,如果存在那么就进行累加,更新到基准的那个map里面去,两个map就合并了
注意:为基准的那个map一定要是mutable可变的。第一个参数是初始值map2,然后第二个参数是一个函数,里面的第一个参数是map2的kv值,然后第二个参数是map1的kv值。然后函数体重定义两个变量遍历取出map1的kv值,然后判断一下map1的key是否在map2里面有,如果有那么就直接+value,就进行累加更新了,如果没有就相当于添加。最后函数的最后一行是返回值,返回map2的kv的那个参数就可以了

package Scala03_shujujiegou

import scala.collection.mutable

//应用案例1、合并Map
class test15_hebingmap {

}
object test15_hebingmap{
  def main(args: Array[String]): Unit = {
    val map1 = Map("a" -> 1,"b" -> 2,"c" -> 6)
    val map2 = mutable.Map("a" -> 3,"b" -> 5, "c" -> 7,"d" -> 4) //要是map2为基准那么要是可变的随时改变
    println(map1 ++ map2) //key都是相同的,就相当于是map2 覆盖了map1

    //就我们大数据而言,同一个key可能有多个分区,按理说map1 和 map2 合并a 的次数应该是4,而不是map2覆盖map1
    //我们可以以某一个map为一个起始的基准,然后再把另一个map里面的每一个value做一个遍历,
    // 每一个key,value判断在不在基准的那个map里,如果不在的话直接添加,如果在的话就把
    //当前的value都取出来,叠加之后再做一个更新操作
    val map3 = map1.foldLeft(map2)((map11,map22) => { //map11是map1,map22是map2
      val key = map22._1 //map2里面的key  比如 "a"
      val value = map22._2 //map2里面的value 比如 3 就是次数
      map11(key) = map11.getOrElse(key,0) + value getOrElse,设置一个初始值如果没有这个元素那么就返回这个初始值
      map11
    }) //因为这是一个键值对,返回的是一个二元组,所以得用foldLeft,因为底层是就是一个二元组所以用这个
    println(map1)
    println(map2)
    println(map3)
  }
}

普通WordCount 案例

1、需求
单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
2、需求分析
在这里插入图片描述
3、案例示例
首先是定义字符串,第二步使用flatMap(a => a.split(" "))方法,进行map映射,扁平化处理,使用空格进行分割。第三步,进行分组按到单词进行分组,一样的单词分到一个组。第四步,进行map转变,获取每个单词的长度,返回一个二元组的键值对,第一个是单词的key,第二个是单词的次数
第五步,使用toList方法转变回list,然后进行排序,因为map是集合,里面是键值对,所以要转变回list才能进行排序

package Scala03_shujujiegou

import scala.collection.mutable

class test3 {

}
object test3{
  def main(args: Array[String]): Unit = {
    //两个Map合并 案例
    val map1 = Map("a" -> 3,"b" -> 6,"c" -> 7)
    val map2 = mutable.Map("a" -> 1,"b" -> 2,"c" -> 4,"d" -> 5) //为基准的那个一定要是可变
    val map3 = map1.foldLeft(map2)((map11,map22) => { //首先以map2为初始值,那么遍历的肯定的就是map1了
      val key = map22._1 //这一步是在进行遍历,将map1的每一个key遍历
      val value = map22._2
      map11(key) = map11.getOrElse(key,0) + value //map11是map2的key和value的值,意思是key要是在map2里面存在那么就进行更新加value值
      map11   //最后的返回值就是map2
    })
    println(map3)
    println("==============")

    //WordCount案例
    //1、第一步定义字符串
    val list = List("hello",
      "word",
      "hello word",
      "hello scala",
      "hello spark from scala",
      "hello flink from scala"
    )
    //2、进行map,和扁平化,split 用空格进行分割
    val list2 = list.flatMap(a => a.split(" "))
    println(list2)
    //3、进行进行分组
    val list3 = list2.groupBy(word => word) //按照单词进行分组,一样的单词分到一组
    println(list3)
    //4、进行map转变,取每个单词的长度
    val list4 = list3.map(kv => (kv._1,kv._2.length)) //进行map映射为一个二元组的,第一个参数是key,第二个是个数的长度
    println(list4)
    //5、转变回list,进行排序,map是一个集合是键值对不能进行排序,所以要转变回list
    val list5 = list4.toList
    println(list5.sortWith(_._2 > _._2).take(3)) //sortWith好进行降序,然后take取前三


  }
}

复杂WordCount 案例

package Scala03_shujujiegou
//复杂WordCount 案例
class test15_fuzaWordCount {

}
object test15_fuzaWordCount{
  def main(args: Array[String]): Unit = {
    val list = List(("hello",1),
      ("word",2),
      ("hello word",3),
      ("hello scala",2),
      ("hello spark from scala",3),
      ("hello flink from scala",5)
    )

    //思路一、直接展开为普通版本
    val newStringList = list.map(
      kv => (kv._1.trim + " ") * kv._2 //只有元组才有这个 ._1 获取元素方式
    )
    println(newStringList)

    //接下来操作与普通版本完全一致

    val list2 = newStringList.flatMap(a => a.split(" "))
    println(list2)

    val list3 = list2.groupBy(word => word) //按照按此进行分组
    println(list3)

    val list4 = list3.map(kv => (kv._1,kv._2.length)) //取key和单词的次数,
    println(list4)
    
    val list5 = list4.toList //转变为list 然后进行排序
    println(list5.sortWith(_._2 > _._2).take(3))

    

  }
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值