scala总结(集合篇)

本文深入讲解Scala集合,包括不可变和可变集合的继承结构、数组、Seq(List)、Set、Map、元组以及常用函数的使用,涵盖从基本操作到高级计算功能,还有WordCount案例分析,并涉及队列和并行集合的概念及应用。
摘要由CSDN通过智能技术生成

第六章 集合

6.1集合简介

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

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

不可变集合:scala.collection.immutable

可变集合: scala.collection.mutable

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

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

6.1.1 不可变集合继承图

scala_不可变集合继承图

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是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

6.1.2 可变集合继承图

scala_可变集合继承图

6.2 数组

6.2.1 不可变数组

1)第一种方式定义数组

val arr1 = new Array[Int](10)

(1)new是关键字

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

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

2)第二种方式定义数组

val arr1 = Array(1, 2)

(1)在定义数组时,直接赋初始值

(2)使用apply方法创建数组对象

3)案例实操

  // 1. 创建一个不可变数组
    // 1) new
    val arr1: Array[Int] = new Array[Int](5)
    // 2) 用伴生对象的apply方法
    val arr2: Array[Int] = Array(1,2,3,4,5)

    println("===========================")

    // 2. 访问数组中元素,做读写操作
    println(s"${arr1(0)} ${arr1.apply(1)} ${arr1(2)} ${arr1(3)} ${arr1(4)}" )
//    println(s"${arr1(5)}")
    arr1(3) = 13
    arr1.update(0, 48)    // arr1(0) = 48
    arr2(2) = 27

    println(arr1.mkString(" "))
    println(arr2.mkString("-"))

    // 3. 遍历所有元素
    // 1) for循环,遍历索引
    for( i <- 0 until arr2.length )
      print(arr2(i) + "\t")

    println()

    for( i <- arr2.indices ) print(arr2(i) + "\t")
    println()

    // 2) for循环直接遍历元素
    for( elem <- arr2 ) print(elem + "\t")

    println()

    // 3) 迭代器
    val iter: Iterator[Int] = arr2.iterator
    while(iter.hasNext)
      print(iter.next() + "\t")

    println()

    // 4) foreach方法
    arr2.foreach( elem => print(elem + "\t") )
    println()
    arr2.foreach( println )

    println("===============================")

    // 4. 向数组中添加元素
    // 生成一个新的数组,原数组不变
    val newArr1: Array[Int] = arr2.:+(20)
    println(arr2.mkString(" "))
    println(newArr1.mkString(" "))

    val newArr2: Array[Int] = newArr1.+:(63)
    println(newArr2.mkString(" "))

    val newArr3 = 15 +: arr1 :+ 39 :+ 9
    val newArr4 = 29 +: 15 +: newArr3
    println(newArr4.mkString(" "))

6.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 Test02_ArrayBuffer {
  def main(args: Array[String]): Unit = {
    // 1. 创建一个可变数组
    val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]()
    val arr2 = ArrayBuffer(3, 56, 29)

    println(arr1)
    println(arr2)

    // 2. 访问数组元素进行读写操作
    println(arr2(1))
    arr2(0) = 12
    println(arr2)

    println("============================")

    // 3. 向数组中添加元素
//    val newArr1 = arr1 :+ 59
//    println(newArr1)

    arr1.append(23)
    println(arr1)
    arr1.append(35, 71)
    println(arr1)

    arr1.prepend(8, 13)
    println(arr1)

    arr1.insert(1, 46, 92)
    println(arr1)

    // 符号方法的调用
    println(arr2)
    arr2 += 23 += 25
    println(arr2)
    37 +=: arr2
    println(arr2)

    // 4. 删除元素
    val a = arr2.remove(2)    // 按索引位置删除
    println(arr2)
    println(a)

    arr2 -= 23    // 按元素值删除
    println(arr2)

    // 5. 增加另一个数组的所有元素
    arr2.appendAll( ArrayBuffer(27,47,80) )
    println(arr2)
    arr2 ++=: arr1
    println(arr1)
    println(arr2)

    // 6. 可变数组和不可变数组的转换
    val arr: ArrayBuffer[Int] = ArrayBuffer(2,4,7)
    val newArr: Array[Int] = arr.toArray
    println(newArr.mkString("-"))
    println(arr)

    val buffer = newArr.toBuffer
    println(buffer)
    println(newArr)

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

说明

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

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

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

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

7.2.4 多维数组

1)多维数组定义

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

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

2)案例实操

定义一个五维数组并遍历

 val arr = Array.ofDim[Int](2,3,4,5,6)
    arr(0)(2)(1)(3)(4) = 100
    arr.foreach(line1 => line1.foreach(line2 => line2.foreach(line3 => line3.foreach(line4 => line4.foreach( println)))))
    arr.foreach(_.foreach(_.foreach(_.foreach(_.foreach( print)))))

6.3 Seq集合(List)

6.3.1 不可变List

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

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

(4)List增加数据

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

2)案例实操

  //(1)List默认为不可变集合
    //(2)创建一个List(数据有顺序,可重复)
    val list1:List[Int] = List(1,2,3,4)
    println(list1)
    //(7)空集合Nil
    val list2:List[Int] = 56::23::12::45::Nil
    println(list2)
    //(4)List增加数据
    val list3 = list1 :+ 5
    println(list3)
    val list4 = 21:: 64 :: list2
    println(list4)
    //(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化
    val list5 = list1 :: list2
    println(list5)
    val list6 = list1 ::: list2
    println(list6)
    //(6)取指定数据
    println(list2(0))
    //(3)遍历List
    list6.foreach(println)

6.3.2 可变List

1)说明

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

(2)向集合中添加数据

(3)打印集合数据

//(1)创建一个可变集合
    val list1 = ListBuffer(1,2,3,50)
    //(2)向集合中添加数据
    list1.insert(1,5)
    list1.append(30)
    list1 += 20
    println(list1)
    //(4)修改数据
    list1.update(2,50)
    list1(1) = 2
    println(list1)

    //(5)删除数据
    list1.remove(2)
    list1.-(50)
    list1 -= 20
    println(list1)
    //(3)打印集合数据
    list1.foreach(println)

6.4 set集合

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

6.4.1不可变set

1)说明

(1)Set默认是不可变集合,数据无序

(2)数据不可重复

(3)遍历集合

2)案例实操

//    (1)Set默认是不可变集合,数据无序
    val set1 = Set(1,2,3,4,5,6)
    println(set1)
    //    (2)数据不可重复
    val set2 = Set(2,3,4,7,1,3)
    println(set2)
    //    (3)遍历集合
    set2.foreach(println)
    for(elem <- set1) print(elem + "\t")
    println()

6.4.2 可变mutable.set

1)说明

(1)创建可变集合mutable.Set

(2)打印集合

(3)集合添加元素

(4)向集合中添加元素,返回一个新的Set

(5)删除数据

2)案例实操

 //    (1)创建可变集合mutable.Set
    val set3 = mutable.Set(1,2,3,4,5,6)
    //    (2)打印集合
    println(set3)
    //    (3)集合添加元素
    set3.add(25)
    set3 += 31
    set3 ++= set2
    println(set3)
    //    (4)向集合中添加元素,返回一个新的Set
    val set4 = set3 + 23
    println(set4)
    //    (5)删除数据
    set4.remove(2)
    set4 -= 5
    println(set4)

6.5 map集合

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

6.5.1 不可变map

1)说明

(1)创建不可变集合Map

(2)循环打印

(3)访问数据

(4)如果key不存在,返回0

2)案例实操

 //    (1)创建不可变集合Map
    val map = Map("a" -> 5 , "b" -> 6 , "c" -> 10 , "d" -> 15)
    //    (2)循环打印
    map.foreach(println)
    println(map.keys)
    println(map.values)
    //    (3)访问数据
    println(map.get("a"))
    //    (4)如果key不存在,返回0
    println(map.getOrElse("e",0))

6.5.2 可变map

1)说明

(1)创建可变集合

(2)打印集合

(3)向集合增加数据

(4)删除数据

(5)修改数据

2)案例实操

  //    (1)创建可变集合
    val map2 = mutable.Map(("a",5),("b",50),("c",13),("d",32))
    //    (2)打印集合
    for (elem <- map2) {print(elem + "\t")}
    println()
    //    (3)向集合增加数据

    map2.put("e",20)
    println(map2)
    //    (4)删除数据
    map2.remove("e")
    println(map)
    //    (5)修改数据
    map2.update("d", 12)
    map2.update("e",15)
    println(map2)

6.6 元组

1)说明

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

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

2)案例实操

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

(2)访问元组

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

 //(1)声明元组的方式:(元素1,元素2,元素3)
    val tuple1:(Int,String,Char) = (25,"a",'a')
    //(2)访问元组
    //(2.1)通过元素的顺序进行访问,调用方式:_顺序号
    println(tuple1._1)
    val tuple2 :(Int,(Int,String),Char,Boolean) = (25,(44,"a"),'c',true)
    println(tuple2._2._1)
    //(2.2)通过索引访问数据
    println(tuple1.productElement(1))
    //(2.3)通过迭代器访问数据
    for (elem <- tuple1.productIterator) {print(elem + "\t")}
    println()

6.7 集合常用函数

6.7.1 基本属性和常用操作

1)说明

(1)获取集合长度

(2)获取集合大小

(3)循环遍历

(4)迭代器

(5)生成字符串

(6)是否包含

2)案例实操

 var list1 = List(1,2,3,4,5)
    //    (1)获取集合长度
    println(list1.length)
    //    (2)获取集合大小
    println(list1.size)
    //    (3)循环遍历
    for (elem <- list1) {print(elem + "\t")}
    println()
    list1.foreach(println)
    //    (4)迭代器
    val iterator = list1.iterator
    while (iterator.hasNext) {
      print(iterator.next() + "\t")
    }
    println()
    //    (5)生成字符串
    println(list1.mkString(" "))
    //    (6)是否包含
    println(list1.mkString(" ").contains(3))

6.7.2 衍生集合

1)说明

(1)获取集合的头

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

(3)集合最后一个数据

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

(5)反转

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

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

(8)并集

(9)交集

(10)差集

(11)拉链

(12)滑窗

2)案例实操

val list1 = List(1,2,3,4,5,6)
    val list2 = List(4,5,6,7,8,9)
    println(list1)
    //    (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))
    println(list2.union(list1))
    //    (9)交集
    println(list1.intersect(list2))
    println(list2.intersect(list1))
    //    (10)差集
    println(list1.diff(list2))
    println(list2.diff(list1))
    //    (11)拉链
    println(list1.zip(list2))
    //    (12)滑窗
    for (elem <- list1.sliding(3)) {print(elem + "\t")}
    println()
    for (elem <- list1.sliding(3,2)) {print(elem + "\t")}
    println()

6.7.3 集合计算初级函数

1)说明

​ (1)求和

​ (2)求乘积

​ (3)最大值

​ (4)最小值

​ (5)排序

2)实操

val list1 = List(3,1,5,20,16,48,4)
    //    (1)求和
    println(list1.sum)
    //    (2)求乘积
    println(list1.product)
    //    (3)最大值
    println(list1.max)
    //    (4)最小值
    println(list1.min)
    //    (5)排序
    println(list1.sorted)
    println(list1.sorted(Ordering[Int].reverse))
    println(list1.sortBy(x => x))
    println(list1.sortBy(x => -x))
    println(list1.sortWith(_ < _))
    println(list1.sortWith(_ > _))

(1)sorted

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

(2)sortBy

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

(3)sortWith

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

6.7.4 集合计算高级函数

1)说明

(1)过滤

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

(2)转化/映射(map)

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

(3)扁平化

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

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

(5)分组(group)

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

(6)简化(归约)

(7)折叠
2)案例实操

  val list1 = List(2,1,5,6,3,4)
    //    (1)过滤
    //    遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
    println(list1.filter(_ % 2 == 0))
    println(list1.filter(_ % 2 == 1))
    //    (2)转化/映射(map)
    //    将集合中的每一个元素映射到某一个函数
    println(list1.map(data => data))
    //    (3)扁平化
    val list2 = List(List(1,2,3),List(4,5,6),List(7,8,9))
    println(list2.flatten)
    //    (4)扁平化+映射 注:flatMap相当于先进行map操作,在进行flatten操作
    //    集合中的每个元素的子元素映射到某个函数并返回新集合
    val List3: List[String] = List("hello world", "hello atguigu", "hello scala")
    List3.flatMap(x => x.split(" "))
    //    (5)分组(group)
    //    按照指定的规则对集合的元素进行分组
    println(list1.groupBy(data => data % 2))
    println("*****************************")
    //     (6)简化
    println(list1.reduce((data1, data2) => data1 + data2)) //等价于sum
    println(list1.reduce(_ - _)) // -17   2-1-5-6-3-4
    println(list1.reduceRight(_ - _)) //-1    2-(1-(5-(6-(3-4))))
    //      (7)折叠
    println(list1.fold(10)(_ - _)) //-11    10-2-1-5-6-3-4
    println(list1.foldRight(10)(_ - _)) //9     2-(1-(5-(6-(3-(4-10)))))

3)案例实操:合并两个map(key相同,value做和)

 val map1 = mutable.Map("a"->1, "b"->2, "c"->3)
    val map2 = mutable.Map("a"->4, "b"->5, "d"->6)
    println(map1)
    println(map2)
    val map3 = map1 ++ map2
    println(map3)
    val map4 = map2.foldLeft(map1){
      (map,kv)  => {
        val k = kv._1
        val v = kv._2
        map(k) = map.getOrElse(k,0) + v
        map
      }
    }
    println(map4)

6.7.5 简单WordCount

1)需求

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

2)案例实操

 val list = List(
      "hello world",
      "hello scala",
      "hello spark",
      "hello spark from scala"
    )
    println(list)
    val list1 = list.flatMap(x => x.split(" "))
      .groupBy(data => data)
      .toList.map(kv => (kv._1, kv._2.length))
      .sortBy( -_._2 )
      .take(3)
    println(list1)

6.7.6 复杂WordCount案例

1)方式一

val tupleList = List(
      ("Hello Scala Spark World ", 4),
      ("Hello Scala Spark", 3),
      ("Hello Scala", 2),
      ("Hello", 1))
    val list2 = tupleList.map(kv => kv._1 * kv._2)
      .flatMap(x => x.split(" "))
      .groupBy(data => data)
      .toList
      .map(kv => (kv._1, kv._2.length))
      .sortBy(-_._2)
      .take(3)
    println(list2)

2)方式二

val list3 = tupleList.flatMap {
      kv => {
        val strings: Array[String] = kv._1.split(" ")
        strings.map(word => (word,kv._2))
      }
    }
      println(list3)
    println(list3.groupBy(data => data._1)
      .mapValues(data => data.map(data => data._2))
      .map(kv => (kv._1,kv._2.sum)))

6.8 队列

1)说明

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

2)案例实操

val queue:mutable.Queue[String] = new mutable.Queue[String]()
    queue.enqueue("a","b","c")
    println(queue.dequeue())
    println(queue.dequeue())
    println(queue.dequeue())

栈和队列大致相同,只不过队列是先进先出,栈是后进先出。栈中也有两个方法,push和pop

6.9 并行集合

1)说明

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

2)案例实操

def main(args: Array[String]): Unit = {
    val result = (0 to 100).map{case _ => Thread.currentThread().getName}
    val result2 = (0 to 100).par.map{case _ => Thread.currentThread().getName}
    println(result)
    println(result2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值