Scala集合

目录

 

一、 集合简介

1.1  不可变集合继承图

1.2 可变集合继承图

二、数组

2.1 不可变数组

2.2 可变数组

2.3 不可变数组与可变数组的转换

2.4 多维数组

三、 Seq集合(List)

3.1 不可变List

3.2 可变ListBuffer

四、Set集合

4.1 可变Set与不可变Set

五、 Map集合

5.1 可变Map与不可变Map

六、 元组

七、 集合常用函数

7.1 基本属性和常用操作

7.2 衍生集合

7.3 集合计算初级函数

7.4 集合计算高级函数

7.5 普通WordCount案例

7.6 复杂WordCount案例

八、 队列

九 、并行集合


一、 集合简介

1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。

2)对于几乎所有的集合类,Scala都同时提供了可变不可变的版本,分别位于以下两个包

不可变集合:scala.collection.immutable

可变集合:scala.collection.mutable

3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象

4)可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象

建议:在操作集合的时候,不可变用符号,可变用方法

1.1  不可变集合继承图

 1)Set、Map是Java中也有的集合

2)Seq是Java没有的,我们发现List归属到Seq了,因此这里的List就和Java不是同一个概念了

3)我们前面的for循环有一个 1 to 3,就是IndexedSeq下的Range

4)String也是属于IndexedSeq

5)我们发现经典的数据结构比如Queue和Stack被归属到LinearSeq(线性序列)

6)大家注意Scala中的Map体系有一个SortedMap,说明Scala的Map可以支持排序

7)IndexedSeq和LinearSeq的区别:

(1)IndexedSeq是通过索引来查找和定位,因此速度快,比如String就是一个索引集合,通过索引即可定位

(2)LinearSeq是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

1.2 可变集合继承图

二、数组

2.1 不可变数组

1)数组

定义:val arr1 = new Array[Int](10) (默认0)

(1)new是关键字

(2)[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any

(3)(10),表示数组的大小,确定后就不可以变化

2)案例实操

object Test03 {
  def main(args: Array[String]): Unit = {
    // 1. 创建数组
    // 1.1 直接new
    val arr1: Array[Int] = new Array[Int](5) //数组默认为0

    //1.2 用伴生对象创建
    //val arr2 = Array.apply(1,2,3,4,5)
    val arr2 = Array(1,2,3,4,5)

    //2.访问数组中元素
    println(arr2(4))  //5
    println(arr2.apply(4))  //5

    //3.数组赋值
    arr2(3) = 10
    println(arr2.mkString(",")) //1,2,3,10,5
    arr1(1) = 23
    println(arr1(1)) //23

    //4.遍历
    //4.1 遍历下标
    for( i <- 0 until arr1.length) print(arr1(i))
    for( i <- arr1.indices ) println(arr1(i))
    //4.2直接遍历数组
    for (elem <- arr1 ) println(elem)
    //4.2迭代器
    val iter = arr2.iterator
    while(iter.hasNext)
      println(iter.next())
    //4.3 调用foreach方法
    arr1.foreach((elem: Int) => println(elem))
    arr2.foreach(println)   //简写

    //5 用不可变数组实现添加数组
    //需要定义一个新的数组来接收返回值
    val newArr1 = arr1 .:+ (27)   //追加在后边
    val newArr2 = arr2  .+: (13)   //添加在最前边
    println(newArr1.mkString(","))
    println(newArr2.mkString(","))
    //添加多个元素
    val newArr3 = newArr1 :+ 35 :+ 13
    val newArr4 = 21 +: 19 +: newArr2 :+ 56
    println(newArr3.mkString(","))
    println(newArr4.mkString(","))
  }
}

2.2 可变数组

1)定义变长数组

val arr01 = ArrayBuffer[Any](3, 2, 5)

(1)[Any]存放任意数据类型

(2)(3, 2, 5)初始化好的三个元素

(3)ArrayBuffer需要引入scala.collection.mutable.ArrayBuffer

2)案例实操

(1)ArrayBuffer是有序的集合

(2)增加元素使用的是append方法(),支持可变参数

object Test04 {
  def main(args: Array[String]): Unit = {
    //1. 创建可变数组
    val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
    val arr2 = ArrayBuffer(1, 2, 3)
    println(arr1) //ArrayBuffer()
    println(arr2) //ArrayBuffer(1, 2, 3)

    //2. 访问数组元素
    println(arr2(2)) //3
    arr2(2) = 15
    arr2.update(1, 27)
    println(arr2) //ArrayBuffer(1, 27, 15)

    // 3. 向数组添加元素
    val newArral1 = arr1 :+ 23
    val newArral2 = 12 +: arr2
    println(arr1) //ArrayBuffer()
    println(arr2) //ArrayBuffer(1, 27, 15)
    println(newArral1) //ArrayBuffer(23)
    println(newArral2) //ArrayBuffer(12, 1, 27, 15)

    println("-------------")
    //调用带英文名称的方法
    arr1.append(13)
    arr2.append(24, 78)
    arr1.prepend(36, 92)
    arr1.insert(1, 22, 18)
    println(arr1) //ArrayBuffer(36, 22, 18, 92, 13)
    println(arr2) //ArrayBuffer(1, 27, 15, 24, 78)

    arr1 += 31
    13 +=: arr1
    println(arr1) //ArrayBuffer(13, 36, 22, 18, 92, 13, 31)

    //4.删除数组元素
    val n = arr1.remove(2)
    println(n) //22
    println(arr1) //ArrayBuffer(13, 36, 18, 92, 13, 31)

    arr1 -= 13
    println(arr1) //ArrayBuffer(36, 18, 92, 13, 31)

    // 还可以用++=进行集合合并
    arr2 ++= ArrayBuffer(23, 45, 67)
    Array(12, 56) ++=: arr2
    println(arr2) //ArrayBuffer(12, 56, 1, 27, 15, 24, 78, 23, 45, 67)

    // 5. 可变数组和不可变数组的转换
    // 5.1 可变转不可变
    val arr: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
    val newArr: Array[Int] = arr.toArray

    // 5.2 不可变转可变
    val buffer: mutable.Buffer[Int] = newArr.toBuffer
    println(buffer) //ArrayBuffer(1, 2, 3)

    //5.2 不可变转可变(利用空的转变成可变)
    val bArr = ArrayBuffer[Int]()
    bArr ++= newArr
    println(bArr)
  }
}

2.3 不可变数组与可变数组的转换

1)说明

arr1.toBuffer  //不可变数组转可变数组

arr2.toArray  //可变数组转不可变数组

(1)arr2.toArray返回结果才是一个不可变数组,arr2本身没有变化

(2)arr1.toBuffer返回结果才是一个可变数组,arr1本身没有变化

2)案例实操

    // 5. 可变数组和不可变数组的转换
    // 5.1 可变转不可变
    val arr: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)
    val newArr: Array[Int] = arr.toArray

    // 5.2 不可变转可变
    val buffer: mutable.Buffer[Int] = newArr.toBuffer
    println(buffer) //ArrayBuffer(1, 2, 3)

    //5.2 不可变转可变(利用空的转变成可变)
    val bArr = ArrayBuffer[Int]()
    bArr ++= newArr
    println(bArr)

2.4 多维数组

1)多维数组定义

val arr = Array.ofDim[Double](3,4)

说明:二维数组中有三个一维数组,每个一维数组中有四个元素

2)案例实操

object Test05 {
  def main(args: Array[String]): Unit = {
    // 1. 创建二维数组
    val arr: Array[Array[Int]] = Array.ofDim[Int](2,3)

    // 2. 访问数组元素
    println(arr(0)(1))
    arr(0)(1) = 13
    println(arr(0)(1))

    // 3. 遍历数组
//    for ( i <- 0 until arr.length; j <- 0 until arr(i).length)
      for (i <- arr.indices; j <- arr(i).indices){
        print(arr(i)(j) + "\t")
        if (j == arr(i).length - 1) println()
      }

    arr.foreach(line => line.foreach(println))
 //   arr.foreach(_.foreach(println))
  }
}

三、 Seq集合(List)

3.1 不可变List

1)说明

(1)List默认为不可变集合

(2)创建一个List(数据有顺序,可重复)
(3)遍历List

(4)List增加数据

(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
(6)取指定数据
(7)空集合Nil

object Test06 {
  def main(args: Array[String]): Unit = {
    // 1. 创建List
    val list1: List[Int] = List(1, 2, 3, 4)
    println(list1) //List(1, 2, 3, 4)

    // 2. 访问List元素,遍历
    println(list1(3)) //4
    for (elem <- list1) println(elem) // 1  2  3  4
    list1.foreach(println)     // 1  2  3  4

    // 3. 向列表里添加数据
    val list2 = 10 +: list1
    val list3 = list2 :+ 24
    println(list1) //List(1, 2, 3, 4)
    println(list2) //List(10, 1, 2, 3, 4)
    println(list3) //List(10, 1, 2, 3, 4, 24)

    // 4. 特殊的List,以及用它来构建列表
    val list4 = list1.::(52)
    val list5 = Nil.::(12)
    println(list4) //List(52, 1, 2, 3, 4)
    println(list5) //List(12)

    val list6 = 13 :: list5
    val list7 = 15 :: 24 :: 67 :: Nil
    println(list6) //List(13, 12)
    println(list7) //List(15, 24, 67)

    // 5. 扁平化
    val list8: List[Any] = list6 :: list7
    println(list8)    //List(List(13, 12), 15, 24, 67)

    val list9: List[Int] = list6 ::: list7
    println(list9)    //List(13, 12, 15, 24, 67)

    val list10 = list6 ++ list7
    println(list10)   //List(13, 12, 15, 24, 67)
  }
}

3.2 可变ListBuffer

1)说明

(1)创建一个可变集合ListBuffer

(2)向集合中添加数据

(3)打印集合数据

2)案例实操

object Test07 {
  def main(args: Array[String]): Unit = {
    // 1. 创建可变List
    val list1: ListBuffer[Int] = new ListBuffer[Int]()
    val list2 = ListBuffer(1,2,3)

    // 2. 添加数据
    list1.append(12)    //ListBuffer(12)
    list2.append(23,57)  //ListBuffer(1, 2, 3, 23, 57)
    list1.append(13,22)  //ListBuffer(12, 13, 22)

    list1 += 65 += 39   //ListBuffer(12, 13, 22, 65, 39)
    11 +=: list2    //ListBuffer(11, 1, 2, 3, 23, 57)
    println(list1)
    println(list2)

    // 3. 合并List
    val list3 = list1 ++ list2
    list1 ++= list2
    list1 ++=: list2
    println(list1)  //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57)
    println(list2) //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57, 11, 1, 2, 3, 23, 57)
    println(list3)  //ListBuffer(12, 13, 22, 65, 39, 11, 1, 2, 3, 23, 57)

    // 4. 修改元素
    list3(2) = 33
    list3.update(4,55)
    println(list3)  //ListBuffer(12, 13, 33, 65, 55, 11, 1, 2, 3, 23, 57)

    // 5. 删除元素
    list3.remove(6,2)  //ListBuffer(12, 13, 33, 65, 55, 11, 3, 23, 57)
    val list4 = list3 - 33 //ListBuffer(12, 13, 65, 55, 11, 3, 23, 57)
    list3 -= 23  //ListBuffer(12, 13, 33, 65, 55, 11, 3, 57)
    println(list4)
    println(list3)
  }
}

四、Set集合

默认情况下,Scala使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包

4.1 可变Set与不可变Set

1)说明

(1)Set默认是不可变集合,数据无序,创建可变集合mutable.Set(向集合中添加元素,返回一个新的Set)

(2)数据不可重复

(3)遍历集合

2)案例实操

object Test09 {
  def main(args: Array[String]): Unit = {
    // 1. 不可变Set
    // 1.1 创建
    val set1: Set[Int] = Set(1, 4, 2, 5, 5, 27, 67)
    println(set1)  //Set(5, 1, 2, 27, 67, 4)

    // 1.2 添加元素
    val set2 = set1 + 21
    println(set1)   //Set(5, 1, 2, 27, 67, 4)
    println(set2)   //Set(5, 1, 21, 2, 27, 67, 4)

    //1.3 合并set
    val set3 = Set(1,27,43,79)
    val set4 = set2 ++ set3
    println(set4)   //Set(5, 1, 21, 2, 27, 67, 43, 4, 79)

    // 1.4 删除元素
    val set5 = set4 - 21
    println(set5)   //Set(5, 1, 2, 27, 67, 43, 4, 79)

    // 2. 可变Set
    // 2.1 创建
    val set6: mutable.Set[Int] = mutable.Set(1,2,3,4)

    // 2.2 添加元素
    set6.add(35)
    println(set6.add(1))  //false

    // 2.3 删除元素
    println(set6.remove(2))
    println(set6)   //Set(1, 35, 3, 4)

    set6 -=2
    val set7 = set6 - 2

    // 2.4 合并集合
    val set8 = set6 ++ set1
    println(set6)
    println(set8)

    set6 ++= set1
    println(set6)
  }
}

 

 

五、 Map集合

Scala中的Map和Java类似,也是一个散列表,它存储的内容也是键值对(key-value映射

5.1 可变Map与不可变Map

1)说明

2)案例实操

object Test08 {
  def main(args: Array[String]): Unit = {
    // 1. 不可变Map
    // 1.1 创建
    val map1: Map[String, Int] = Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4)
    println(map1)

    // 1.2 遍历map元素
    map1.foreach(println) //(a,1)(b,2)(c,3)(d,4)
    map1.keys.foreach(println) //abcd
    map1.values.foreach(println) //1234

    println("*************")
    // 1.3 单独访问元素
    println(map1.get("c").getOrElse(0)) //3
    println(map1.getOrElse("c", 0)) // 3

    // 2. 可变Map
    // 2.1 创建
    val map2: mutable.Map[String, Int] = mutable.Map("a" -> 1, "b" -> 2, "c" -> 3, "d" -> 4)
    // 2.2 添加元素
    map2.put("d", 67)
    map2.put("e", 13)

    map2 += ("f" -> 25)
    println(map2)

    // 2.3 修改和删除
    map2.update("d", 31)
    println(map2("d"))
    map2("b") = 69

    map2.remove("c")
    map2 -= "c"
    map2 .-= ("c","d")
    println(map2)

    // 2.4 合并两个Map
    val map3 = map1 ++ map2
    map2 ++= map1
    println(map1)
    println(map2)
    println(map3)
  }
}

六、 元组

1)说明

元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。说的简单点,就是将多个无关的数据封装为一个整体,称为元组。

注意:元组中最大只能有22个元素。

2)案例实操

(1)声明元组的方式:(元素1,元素2,元素3)

(2)访问元组

(3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶

object Test08_Tuple {
  def main(args: Array[String]): Unit = {
    // 1. 创建一个元组
    val tuple1: (Int, String, Double, Char) = (100, "hello", 12.3, 'c')
    println(tuple1)

    // 2. 访问元组数据
    //(2.1)通过元素的顺序进行访问,调用方式:_顺序号
    println(tuple1._3)
//    tuple1._2 = ""      // error, 不能重新赋值
                        
    //(2.2)通过索引访问数据
    println(tuple1.productElement(0))

    // 3. 遍历数据
//    for( elem <- tuple1 ) println(elem)    // 元组中没有foreach方法
//    tuple1.foreach()
    //通过迭代器访问数据
    for( elem <- tuple1.productIterator) println(elem)

    // 4. 元组和map的键值对 //Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶       
//    val map1 = Map("a"->1, "b"->2, "c"->3)
//    println(map1)
    val map1 = Map(("a",1), ("b",2), ("c",3))
    map.foreach(tuple=>{println(tuple._1 + "=" + tuple._2)})

    // 5. 嵌套元组
    val tuple2: (Int, Double, String, List[Int], (Char, Int)) = (12, 0.9, "hi", List(1, 2), ('c', 15))
    println(tuple2._5._2)

    val tuple3 = (1,1,2,2)
    val tuple4 = (("a", 1), ("a", 2))
    println(tuple4)

  }
}

七、 集合常用函数

7.1 基本属性和常用操作

1)说明

(1)获取集合长度

(2)获取集合大小

(3)循环遍历

(4)迭代器

(5)生成字符串

(6)是否包含

2)案例实操

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
    println(list.size)

    //(3)循环遍历
    list.foreach(println)

    //(4)迭代器
    for (elem <- list.itera	tor) {
      println(elem)
    }

    //(5)生成字符串
    println(list.mkString(","))

    //(6)是否包含
    println(list.contains(3))
  }
}

7.2 衍生集合

1)说明

(1)获取集合的头

(2)获取集合的尾(不是头的就是尾)

(3)集合最后一个数据

(4)集合初始数据(不包含最后一个)

(5)反转

(6)取前(后)n个元素

(7)去掉前(后)n个元素

(8)并集

(9)交集

(10)差集

(11)拉链

(12)滑窗

2)案例实操

object Test05 {
  def main(args: Array[String]): Unit = {
    val list1 = List(1,2,3,4,5,6,6,7)
    val list2 = List(5,4,6,7,8,9,10,11,12)

    //    (1)获取集合的头
    println(list1.head)   //1
    //    (2)获取集合的尾(不是头的就是尾)
    println(list1.tail)   //List(2, 3, 4, 5, 6, 6, 7)
    //    (3)集合最后一个数据
    println(list1.last)   //7
    //    (4)集合初始数据(不包含最后一个)
    println(list2.init)  //List(5, 4, 6, 7, 8, 9, 10, 11)
    //    (5)反转
    println(list2.reverse)  //List(12, 11, 10, 9, 8, 7, 6, 4, 5)
    //    (6)取前(后)n个元素
    println(list1.take(3))   //List(1, 2, 3)
    println(list2.takeRight(3))  //List(10, 11, 12)
    //    (7)去掉前(后)n个元素
    println(list1.drop(3))   //List(4, 5, 6, 6, 7)
    //    (8)并集
    val union = list1.union(list2)
    println(union) //List(1, 2, 3, 4, 5, 6, 6, 7, 5, 4, 6, 7, 8, 9, 10, 11, 12)
    println(list2.union(list1)) //List(5, 4, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 6, 7)

    //set的并集去重的,set本身数据无序,不可重复
    val set1 = Set(1,2,3,4,5,6,7)
    val set2 = Set(4,5,6,7,8,9,10,11,12)
    val unionSet = set1.union(set2)
    println(unionSet)  //Set(5, 10, 1, 6, 9, 2, 12, 7, 3, 11, 8, 4)
    println(set2.union(set1))   //Set(5, 10, 1, 6, 9, 2, 12, 7, 3, 11, 8, 4)

    //    (9)交集
    val intersectionSet: Set[Int] = set1.intersect(set2)
    println(intersectionSet)   //Set(5, 6, 7, 4)

    println(list1.intersect(list2))  //List(4, 5, 6, 7)
    println(list2.intersect(list1))   //List(5, 4, 6, 7)

    //    (10)差集
    println(list1.diff(list2))  //List(1, 2, 3, 6)
    println(list2.diff(list1))  //List(8, 9, 10, 11, 12)

    //    (11)拉链
    //注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
    println(list1.zip(list2))

    //    (12)滑窗
    // 12.1 单参数,步长为1
    for(elem <- list2.sliding(5)) println(elem)  //List(5, 4, 6, 7, 8) List(4, 6, 7, 8, 9) List(6, 7, 8, 9, 10) List(7, 8, 9, 10, 11) List(8, 9, 10, 11, 12)
    // 12.2 两参数,size和步长
    for(elem <- list2.sliding(5,3)) println(elem)  //List(5, 4, 6, 7, 8) List(7, 8, 9, 10, 11) List(10, 11, 12)
    // 12.3 整体滑动
    for( elem <- list2.sliding(3,3)) println(elem)  //List(5, 4, 6) List(7, 8, 9) List(10, 11, 12)
    }
}

7.3 集合计算初级函数

1)说明

       (1)求和

       (2)求乘积

       (3)最大值

       (4)最小值

       (5)排序

2)实操

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)排序
    // (5.1)按照元素大小排序
    println(list.sortBy(x => x))

    // (5.2)按照元素的绝对值大小排序
    println(list.sortBy(x => x.abs))

    // (5.3)按元素大小升序排序
   println(list.sortWith((x, y) => x < y))

   // (5.4)按元素大小降序排序
    println(list.sortWith((x, y) => x > y))
  }
}

(1)sorted

对一个集合进行自然排序,通过传递隐式的Ordering

(2)sortBy

对一个属性或多个属性进行排序,通过它的类型。

(3)sortWith

基于函数的排序,通过一个comparator函数,实现自定义排序的逻辑。

7.4 集合计算高级函数

1)说明

(1)过滤

       遍历一个集合并从中获取满足指定条件的元素组成一个新的集合

(2)转化/映射(map

       将集合中的每一个元素映射到某一个函数

(3)扁平化

(4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作

        集合中的每个元素的子元素映射到某个函数并返回新集合

(5)分组(group)

       按照指定的规则对集合的元素进行分组

(6)简化(归约)      

(7)折叠

2)实操

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

    // 1. 过滤
    // 筛选所有的偶数
    val newList: List[Int] = for ( i <- list if i % 2 ==0) yield i
    println(newList)  //List(2, 4, 6, 8)

    val evenList = list.filter(_ % 2 == 0)
    println(evenList) //List(2, 4, 6, 8)

    //2.转化/映射==>map
    println(list.map(_ * 2 + "data"))  //List(2data, 4data, 6data, 8data, 10data, 12data, 14data, 16data, 18data)
    println(list.map(x => x + 1))  //List(2, 3, 4, 5, 6, 7, 8, 9, 10)

    // 3. 扁平化
    val nestedList: List[List[Int]] = List(List(1,2,4),List(3,7,9),List(23,46,67))
    val flatList: List[Int] = nestedList.flatten
    println(flatList)  //List(1, 2, 4, 3, 7, 9, 23, 46, 67)

    //4. 扁平映射 ==> 注:flatMap相当于先进行map操作,在进行flatten操作
    val stringList: List[String] = List("hello scala", "hello world", "hello atguigu")
    println(stringList.map(str => str.split(" ")).flatten)   //List(hello, scala, hello, world, hello, atguigu)
    println(stringList.flatMap(_.split(" ")))  //List(hello, scala, hello, world, hello, atguigu)

    // 5. 分组
    // 按照奇偶性分组

    val groupedMap: Map[String,List[Int]] = list.groupBy(data => if(data % 2 == 0) "偶数" else "奇数")
    println(groupedMap)

    // 按照字符串首字母分组
    val strings: List[String] = List("china","canada","usa","japan","uk")
    println(strings.groupBy(_.charAt(0)))
  }
}

3Reduce方法

Reduce简化(归约) :通过指定的逻辑将集合中的数据进行聚合,从而减少数据,最终获取结果。

    案例实操

object Test07 {
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4)
    // 1. reduce
    val res1 = list.reduce((a:Int,b:Int) => a + b)
    val res2 = list.reduce(_ + _)
    val res3 = list.reduceLeft(_+_)
    val res4 = list.reduceRight(_+_)

    println(res1)   //10
    println(res2)   //10
    println(res3)   //10
    println(res4)   //10

     从源码的角度,reduce底层调用的其实就是reduceLeft
    // 关于左右规约,减法规约
    println(list.reduceLeft(_ - _))  //-8
    println(list.reduceRight(_ - _)) //-2

    val list2 = List(3,4,5,8,10)
    println(list2.reduceLeft(_ - _))  // -24  3-4-5-8-10
    println(list2.reduceRight(_ - _))  // 6  3-(4-(5-(8-10)))

    //2.fold
    val res5 = list.fold(10)(_ - _) // 0    10-1-2-3-4
    println(res5)

    println(list2.foldRight(11)(_ - _))   // -5  3-(4-(5-(8-(10-11)))
  }
}

4Fold方法

Fold折叠:简化的一种特殊情况。

    (1)案例实操: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)
    }
}

 (2)案例实操:两个集合合并

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)
    }
}

7.5 普通WordCount案例

1)需求

       单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果

2)需求分析

3)案例实操

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 Test13_WordCount {
  def main(args: Array[String]): Unit = {
    // 1. 简单版本
    val stringList = List(
      "hello",
      "hello world",
      "hello scala",
      "hello spark in scala",
      "hello flink in scala"
    )

    // 1.1 按空格切分字符串,得到打散的word
    val wordList0 = stringList.map( str => str.split(" ") )
//    println(wordList0.flatten)

    val wordList = stringList.flatMap( _.split(" ") )
    println(wordList)

    // 1.2 按照单词自身作为key分组
    val groupMap: Map[String, List[String]] = wordList.groupBy( word => word )
    println(groupMap)

    // 1.3 对分组的word列表进行length统计,得到(word,count)
    val countMap: Map[String, Int] = groupMap.map( kv => (kv._1, kv._2.length) )
    println(countMap)

    // 1.4 排序取top3
    val sortList: List[(String, Int)] = countMap
      .toList    // 转换成list
//        .sortWith( (data1, data2) => data1._2 > data2._2 )
      .sortWith( _._2 > _._2 )    // 按照count值从大到小排序
      .take(3)    // 选取前3

    println(sortList)

7.6 复杂WordCount案例

1)方式一

object TestWordCount {

    def main(args: Array[String]): Unit = {

        // 第一种方式(不通用)
        val tupleList = List(("Hello Scala Spark World ", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))

        val stringList: List[String] = tupleList.map(t=>(t._1 + " ") * t._2)

        //val words: List[String] = stringList.flatMap(s=>s.split(" "))
        val words: List[String] = stringList.flatMap(_.split(" "))

        //在map中,如果传进来什么就返回什么,不要用_省略
        val groupMap: Map[String, List[String]] = words.groupBy(word=>word)
        //val groupMap: Map[String, List[String]] = words.groupBy(_)

        // (word, list) => (word, count)
        val wordToCount: Map[String, Int] = groupMap.map(t=>(t._1, t._2.size))

        val wordCountList: List[(String, Int)] = wordToCount.toList.sortWith {
            (left, right) => {
                left._2 > right._2
            }
        }.take(3)

        //tupleList.map(t=>(t._1 + " ") * t._2).flatMap(_.split(" ")).groupBy(word=>word).map(t=>(t._1, t._2.size))
        println(wordCountList)
    }
}

2)方式二

object TestWordCount {
    def main(args: Array[String]): Unit = {
        val tuples = List(("Hello Scala Spark World", 4), ("Hello Scala Spark", 3), ("Hello Scala", 2), ("Hello", 1))

        // (Hello,4),(Scala,4),(Spark,4),(World,4)
        // (Hello,3),(Scala,3),(Spark,3)
        // (Hello,2),(Scala,2)
        // (Hello,1)
        val wordToCountList: List[(String, Int)] = tuples.flatMap {
            t => {
                val strings: Array[String] = t._1.split(" ")
                strings.map(word => (word, t._2))
            }
        }

        // Hello, List((Hello,4), (Hello,3), (Hello,2), (Hello,1))
        // Scala, List((Scala,4), (Scala,3), (Scala,2)
        // Spark, List((Spark,4), (Spark,3)
        // Word, List((Word,4))
        val wordToTupleMap: Map[String, List[(String, Int)]] = wordToCountList.groupBy(t=>t._1)

        val stringToInts: Map[String, List[Int]] = wordToTupleMap.mapValues {
            datas => datas.map(t => t._2)
        }
        stringToInts

        /*
        val wordToCountMap: Map[String, List[Int]] = wordToTupleMap.map {
            t => {
                (t._1, t._2.map(t1 => t1._2))
            }
        }

        val wordToTotalCountMap: Map[String, Int] = wordToCountMap.map(t=>(t._1, t._2.sum))
        println(wordToTotalCountMap)
        */
    }
}

 2)方式三

object Test10 {
  def main(args: Array[String]): Unit = {
    val tupleList: List[(String, Int)] = List(
      ("hello world", 1),
      ("hello scala", 2),
      ("hello spark in scala", 3),
      ("hello flink in scala", 4)
    )

    val wordCountMap1 = tupleList.flatMap(kv =>{
      val strList = kv._1.split(" ")
      strList.map(word => (word,kv._2))
    })                                    //List((hello,1), (world,1), (hello,2), (scala,2), (hello,3), (spark,3), (in,3), (scala,3), (hello,4), (flink,4), (in,4), (scala,4))
        .groupBy(_ ._1 )                 //Map(in -> List((in,3), (in,4)), world -> List((world,1)), flink -> List((flink,4)), spark -> List((spark,3)), scala -> List((scala,2), (scala,3), (scala,4)), hello -> List((hello,1), (hello,2), (hello,3), (hello,4)))
        .toList                         // List((in,List((in,3), (in,4))), (world,List((world,1))), (flink,List((flink,4))), (spark,List((spark,3))), (scala,List((scala,2), (scala,3), (scala,4))), (hello,List((hello,1), (hello,2), (hello,3), (hello,4))))
        .map(kv => {
          (kv._1,kv._2.map(_._2))
        })                                //List((in,List(3, 4)), (world,List(1)), (flink,List(4)), (spark,List(3)), (scala,List(2, 3, 4)), (hello,List(1, 2, 3, 4)))
        .map(kv => (kv._1,kv._2.sum))    //List((in,7), (world,1), (flink,4), (spark,3), (scala,9), (hello,10))
        .sortBy(_._2).reverse            //List((hello,10), (scala,9), (in,7), (flink,4), (spark,3), (world,1))
        .take(3)                        //List((hello,10), (scala,9), (in,7))
    println(wordCountMap1)

  }
}

八、 队列

1)说明

Scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出。进队和出队的方法分别为enqueue和dequeue。

2)案例实操

object TestQueue {
    def main(args: Array[String]): Unit = {
        val que = new mutable.Queue[String]()
        que.enqueue("a", "b", "c")

        println(que.dequeue())
        println(que.dequeue())
        println(que.dequeue())
    }
}

九 、并行集合

1)说明

Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算。

2)案例实操

object TestPar {
    def main(args: Array[String]): Unit = {

        val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}
        val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}

        println(result1)
        println(result2)
    }
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Scala中的集合分为可变集合和不可变集合两种。不可变集合一旦创建,就不能进行修改。Scala中默认使用不可变集合,如果需要修改集合中的元素,则需要使用可变集合Scala中的集合包括List、Set、Map等。常用的集合操作有: 1. 创建集合:可以使用不可变集合的apply方法或者可变集合的new关键字创建集合。 2. 遍历集合:可以使用for循环、foreach方法或者map方法遍历集合。 3. 过滤元素:可以使用filter方法过滤集合中不符合条件的元素。 4. 转换集合:可以使用map方法将集合中的元素进行转换。 5. 排序集合:可以使用sorted方法对集合中的元素进行排序。 6. 操作集合:可以使用集合的各种方法进行元素的添加、删除、更新等操作。 示例代码: ``` // 创建不可变列表 val list = List(1, 2, 3) // 遍历列表 for (i <- list) { println(i) } // 过滤列表中的偶数 val filteredList = list.filter(_ % 2 == 0) // 转换列表中的元素 val mappedList = list.map(_ * 2) // 排序列表 val sortedList = list.sorted // 创建可变列表 val mutableList = scala.collection.mutable.ListBuffer(1, 2, 3) // 添加元素到可变列表 mutableList += 4 // 删除可变列表中的元素 mutableList -= 2 // 更新可变列表中的元素 mutableList(0) = 0 // 遍历可变列表 mutableList.foreach(println) ``` 以上是Scala集合的基本用法,具体使用时可以根据需要选择不同的集合类型和方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值