Scala入门(七)集合

十、Scala从入门到精通一一集合 目录10.1、数据结构特点10.1.1、Scala集合基本介绍10.1.2、可变集合和不可变集合举例三级目录 10.1、数据结构特点 10.1.1、Scala集合基本介绍 uml => 统一建模语言 1、Scala同时支持不可变集合和可变集合,不可变集合可以安全的并发访问 两个主要的包: 不可变集合:scala.collection.immutable 可变集合:scala.collecti... 阅读详情

总目录

1.集合简介

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.数组

2.1 不可变数组

1)第一种方式定义数组

定义:val arr = new Array[Int](10)

(1)new 是关键字

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

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

2)案例

object Test_Array {
    def main(args: Array[String]): Unit = {
        // 创建数组
        val arr01: Array[Int] = new Array[Int](5)
        println(arr01.length) // 5
        // 访问数组中某个元素
        // 在访问元素时,arr(0)其实就是arr01.apply(0),是调用Array类的apply方法;但arr01.apply(0) = 1是不行的
        println(arr01(1)) // 0
        //(2)数组赋值
        //(2.1)修改某个元素的值
        arr01(3) = 10
        //(2.2)采用方法的形式给数组赋值
        arr01.update(0,1)
        //(3)遍历数组
        //(3.1)查看数组
        println(arr01.mkString(","))
        //(3.2)普通遍历
        // for(i <- 0 until arr01.length) println(arr01(i))
        // indices在源码中的解释是def indices: Range = 0 until length
        // for(i <- arr01.indices) println(arr01(i))
        for (i <- arr01) println(i)
        // 迭代器
        // val iter = arr01.iterator
        // while (iter.hasNext) println(iter.next())
        //(3.3)简化遍历
        // arr01.foreach((x)=>{println(x)})
        // arr01.foreach(println(_))
        arr01.foreach(println)
        //(4)增加元素(由于创建的是不可变数组,增加元素,其实是产生新的数组,可以通过输出前后地址验证)
        println(arr01.mkString(","))
        // :+ 在后方追加
        // arr01 :+ 5也可以(注:在后面添加Array应在符号前)
        val newArr: Array[Int] = arr01.:+(5)
        println(newArr.mkString(","))
        // +: 在最前方添加
        // 3 +: newArr也可以(注:在前面添加Array应在符号后)
        val newArr1: Array[Int] = newArr.+:(3)
        println(newArr1.mkString(","))
    }
}

3)第二种方式定义数组

val arr1 = Array(1, 2)

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

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

4)案例

object Test_Array {
    def main(args: Array[String]): Unit = {
        // 实际是调用了apply方法。Array.apply(1, 3, 5)
        val arr02 = Array(1, 3, 5)
        println(arr02.length)
        for (i <- arr02) {
            println(i)
        }
    }
}

2.2 可变数组

1)定义变长数组

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

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

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

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

注意:(1)ArrayBuffer 是有序的集合

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

object Test_ArrayBuffer {
    def main(args: Array[String]): Unit = {
        // 创建可变数组
        // val arr1 = new ArrayBuffer[Int]()
        // 利用apply方法创建ArrayBuffer对象
        val arr1 = ArrayBuffer(1, 3, 5)

        // 访问元素
        println(arr1(0))

        // 修改元素
        // arr1(0) = 3
        // println(arr1.mkString(","))

        // 遍历与不可变数组类似,不再赘叙

        // 添加元素
        // 不可变数组一般使用符号(虽然可变数组也可用,但不推荐,因为会创建一个新的数组)
        val newArr = arr1 :+ 13
        println(newArr.mkString(","))
        println(arr1 == newArr) // false
        // 可变数组常见添加元素操作,但不推荐进行类似于arr1 += 13这种操作后赋值(这个与不可变数组相异)
        // 因为赋值的是引用,故而一个改变,另一个也会改变
        // val newArr1 = arr1 += 13
        // println(newArr1.mkString(","))
        // println(arr1 == newArr1)  // true,引用相等
        // 后面追加
        // arr1 += 13
        // println(arr1.mkString(","))
        // 前面添加
        // 13 +=: arr1
        // println(arr1.mkString(","))
        // 可变集合更推荐使用方法而非符号(虽然符号也是方法,但此处指的是那种明确的英文名称方法)
        // 末尾添加,可以添加多个
        arr1.append(13)
        println(arr1.mkString(","))
        // 前面添加,可以添加多个
        arr1.prepend(13)
        println(arr1.mkString(","))
        // 指定位置添加,可以添加多个(第一个参数是索引,其余是要添加的元素)
        arr1.insert(1, 13)
        println(arr1.mkString(","))
        // insertAll方法可以直接在指定位置将一个数组所有元素加入
        // 相应的还有appendAll和prependAll,就不再赘叙
        arr1.insertAll(1, Array(1, 3, 5))
        println(arr1.mkString(","))

        // 删除元素
        // remove(n: Int),n是索引,即删除指定索引位置元素
        arr1.remove(3)
        println(arr1.mkString(","))
        // remove(n: Int, count: Int),n是索引,count是数目,即删除指定索引位置元素count个元素
        arr1.remove(3, 2)
        println(arr1.mkString(","))
        // 按照元素本身的值来进行删除(需要使用符号),只会删除第一个对应的元素
        arr1 -= 13
        println(arr1.mkString(","))
    }
}

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

1)说明

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

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

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

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

2)案例

// 不可变数组与可变数组的转换
val arr: ArrayBuffer[Int] = ArrayBuffer(1, 3, 5)
// 可变转变为不可变
val newArr2: Array[Int] = arr.toArray
println(newArr2.mkString(","))
println(arr)
// 不可变转变为可变
val buffer = newArr2.toBuffer
println(buffer)
println(newArr2)

2.4 多维数组

1)多维数组定义

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

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

2)案例

object Test_MulArray {
    def main(args: Array[String]): Unit = {
        // 创建二维数组
        // ofDim方法可以用于创建多维数组(最高5维),参数的数目即是维度
        // 如下示例即为二维数组,二行三列
        val array: Array[Array[Int]] = Array.ofDim[Int](2, 3)

        // 访问元素
        println(array(0)(1))

        // 赋值
        array(0)(1) = 1
        println(array(0)(1))

        // 遍历(不可直接使用mkString,会输出引用)
        // for(i <- 0 until array.length; j <- 0 until array(i).length) println(array(i)(j))
        // for(i <- array.indices; j <- array(i).indices) println(array(i)(j))
        // array.foreach(line => line.foreach(println))
        // array.foreach(_.foreach(println))
        for(i <- array.indices) println(array(i).mkString(","))
    }
}

3.列表List

3.1 不可变List

1)说明

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

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

(3)遍历 List

(4)List 增加数据

(5)集合间合并:将一个整体拆成一个一个的个体,称为扁平化

(6)取指定数据

(7)空集合 Nil

2)案例

object Test_List {
    def main(args: Array[String]): Unit = {
        // 创建一个List
        // 由于List本身是一个抽象类
        // 且被sealed(密封,用此修饰后,当前类的子类不可定义在类文件之外)修饰,故不可直接用new关键字创建
        // 在此处是调用List类伴生对象的apply方法创建的
        val list1 = List(1, 3, 5)
        println(list1)

        // 访问List元素
        // list1(1) = 10这类赋值操作不行
        println(list1(1))

        // 遍历List元素
        // list1.foreach(println)

        // 添加元素
        // 列表头部添加
        // 10 +: list1也可以
        val list2 = list1.+:(10)
        // 列表尾部添加
        // list2 :+ 10也可以
        val list3 = list1.:+(10)
        println(list2)
        println(list3)

        println("-------------------------")

        // 可以用于在列表头部添加元素,但一般不这么使用
        val list4 = list1.::(10)
        println(list4)
        // 一般用于配合Nil(空列表)创建新列表
        val list5 = Nil.::(10)
        println(list5)
        val list6 = 10 :: Nil
        println(list6)
        val list7 = 10 :: 13 :: 15 :: Nil
        println(list7)

        // 合并列表
        // 在这里是直接把整个列表加入另一个列表的头部,而非将数据合并
        val list8 = list6 :: list7
        println(list8)
        // 将后一个列表的元素合并前一个列表的尾部
        // 扁平化:将整体拆分为一个一个的个体
        // list6 ++ list7也可以
        val list9 = list6 ::: list7
        println(list9)
    }
}

3.2 可变ListBuffer

1)说明

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

(2)向集合中添加数据

(3)打印集合数据

2)案例

object Test_ListBuffer {
    def main(args: Array[String]): Unit = {
        // 创建可变列表
        // 利用new关键字创建
        // val list1: ListBuffer[Int] = new ListBuffer[Int]()
        // 利用伴生对象的apply方法创建
        val list1: ListBuffer[Int] = ListBuffer(1, 3, 5)
        println(list1)
        println("------------------------")

        // 添加元素
        // 在头部添加
        list1.prepend(10, 13)
        println(list1)
        println("------------------------")
        // 在尾部添加
        list1.append(10, 13)
        println(list1)
        println("------------------------")
        // 指定位置添加
        list1.insert(1, 1, 3)
        println(list1)
        println("------------------------")
        // 用符号添加
        // 尾部添加
        // list1 += 10 += 13
        // println(list1)
        // println("------------------------")
        // 头部添加
        // 10 +=: 13 +=: list1
        // println(list1)
        // println("------------------------")
        // 同时使用
        // 10 +=: 13 +=: list1 += 10 += 13
        // println(list1)
        // println("------------------------")

        // 合并列表
        // 此种方法list1与list2的值不会发生改变
        val list2: ListBuffer[Int] = ListBuffer(10, 13)
        val list3 = list1 ++ list2
        println(list3)
        println("------------------------")
        // 此种方法list1会发生改变,list2不会改变,是在list1尾部添加
        list1 ++= list2
        println(list1)
        println("------------------------")
        // 此种方法是list2会发生改变,list1不会改变,是在list2头部添加
        list1 ++=: list2
        println(list2)
        println("------------------------")

        // 修改元素
        // 实则是调用了update方法
        // list2.update(1, 30)
        list2(1) = 30
        println(list2)
        println("------------------------")

        // 删除元素
        // 删除指定位置的元素
        list2.remove(1)
        println(list2)
        println("------------------------")
        // 删除指定的元素
        // 只会删除第一次出现的
        list2 -= 10
        println(list2)
    }
}

4.Set集合

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

4.1 不可变Set

1)说明

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

(2)数据不可重复

(3)遍历集合

2)案例

object Test_ImmutableSet {
    def main(args: Array[String]): Unit = {
        // 创建set
        // 同样,由于Set是一个特质,不可使用new关键字创建对象
        // 在此处使用其伴生对象的apply方法创建
        // 如果有重复的元素会自动去重
        val set1: Set[Int] = Set(1, 3, 5)
        println(set1)
        println("------------------------------")

        // 添加元素
        // 由于Set无序,所以添加的位置无意义
        // set1.+(20)
        val set2 = set1 + 20
        println(s"set1 = $set1")
        println(s"set2 = $set2")
        println("------------------------------")

        // 合并Set
        val set3 = Set(10, 13)
        // +不能完成此操作,只能用来添加元素
        // 在合并时,相同的元素会进行去重
        val set4 = set2 ++ set3
        println(set4)
        println("------------------------------")

        // 删除元素
        val set5 = set3 - 13
        println(s"set3 = $set3")
        println(s"set5 = $set5")
        println("------------------------------")
    }
}

4.2 可变Set

1)说明

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

(2)打印集合

(3)集合添加元素

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

(5)删除数据

2)案例

object Test_MutableSet {
    def main(args: Array[String]): Unit = {
        // 创建Set
        // 如果直接使用Set创建,默认会创建不可变的集合
        val set1 = mutable.Set(1, 3, 5)
        println(set1)
        println("-------------------------")

        // 添加元素
        // 直接使用+,集合内容不改变
        // 若不进行赋值,原值不改变
        // val set2 = set1 + 13(set2值即为已添加元素的数组)
        // println(set1)
        // println(set2)
        set1 += 13
        println(set1)
        println("-------------------------")
        // add方法返回值为Boolean,具体实现见源码(实际上还是调用了+=)
        // 若是集合中已经存在,则返回false,反之返回true
        set1.add(10)
        println(set1)
        println("-------------------------")

        // 删除元素
        set1 -= 10
        println(set1)
        println("-------------------------")
        // remove方法返回值为Boolean,具体实现见源码(实际上还是调用了-=)
        // 若是集合中不存在,则返回false,反之返回true
        set1.remove(13)
        println(set1)
        println("-------------------------")

        // 合并集合
        // 合并时会进行去重
        val set3 = mutable.Set(10, 13)
        println(set1)
        println(set3)
        println("-------------------------")
        val set4 = set1 ++ set3
        println(set1)
        println(set3)
        println(set4)

        println("-------------------------")
        set1 ++= set3
        println(set1)
        println(set3)
    }
}

5.Map集合

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

5.1 不可变Map

1)说明

(1)创建不可变集合 Map

(2)循环打印

(3)访问数据

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

2)案例

object Test_ImmutableMap {
    def main(args: Array[String]): Unit = {
        // 创建Map
        // 默认为不可变类型,且由于Map是特征,不能直接new
        // 且不可变Map不能直接添加元素
        val map1: Map[String, Int] = Map("1" -> 1, "2" -> 2, "3" -> 3)
        println(map1)
        // 由于有三个元素,故而为Map3
        println(map1.getClass)  // class scala.collection.immutable.Map$Map3
        println("-----------------------------")

        // 遍历元素
        // 非简写形式:map1.foreach( (kv: (String, Int)) => println(kv) )
        map1.foreach(println)
        println("-----------------------------")

        // 访问某一个key的value
        // get返回值为Option类型,可防止空指针异常,将其包装成Option来处理
        println(map1.get("1"))
        // Some取值可用get方法,返回值即为value的值
        println(map1.get("1").get)
        // 若获取不存在的键,则结果为None
        // 注:在此种情况下不能使用Some的get方法,会抛出异常
        println(map1.get("10"))
        // 若使用getOrElse方法,存在则返回相应值,不存在则返回指定默认值
        println(map1.getOrElse("10", 0))
        // 类似于get.get,若不存在会抛出异常
        println(map1("1"))
        println("-----------------------------")

        // 取map中所有的key或者所有的value
        for(key <- map1.keys) {
            println(s"$key -> ${map1.get(key)}")
        }
    }
}

5.2 可变Map

1)说明

(1)创建可变集合

(2)打印集合

(3)向集合增加数据

(4)删除数据

(5)修改数据

2)案例

object Test_MutableMap {
    def main(args: Array[String]): Unit = {
        // 创建Map
        val map1: mutable.Map[String, Int] = mutable.Map("1" -> 1, "2" -> 2, "3" -> 3)
        println(map1)
        // HashMap是无序的
        println(map1.getClass)
        println("----------------------------")

        // 添加元素
        map1.put("4", 4)
        map1.put("5", 5)
        println(map1)
        println("----------------------------")

        map1 += (("6", 6))
        map1 += (("7", 7))
        println(map1)
        println("----------------------------")

        // 删除元素
        // 只需要指定key就行了
        println(map1.get("7"))
        map1.remove("7")
        println(map1.getOrElse("7", 0))

        map1 -= "5"
        println(map1)
        println("----------------------------")

        // 修改元素
        map1.update("3", 333)
        println(map1)

        map1 += (("3", 777))
        println(map1)
        println("----------------------------")

        // 合并Map
        val map2: Map[String, Int] = Map("10" -> 10, "13" -> 13)
        // 注:不仅仅是添加,如果有相同的key,会以map2的value覆盖
        // 可变Map与上述类似
        map1 ++= map2
        println(map1)
        // 不可变Map不可直接添加合并,但可以通过赋给新的对象来实现
        val map3: Map[String, Int] = map2 ++ map1
        println(map3)
    }
}

6.元组

1)说明

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

一个整体,称为元组。

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

2)案例

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

(2)访问元组

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

object Test_Tuple {
    def main(args: Array[String]): Unit = {
        // 创建元组
        val tuple: (Int, String, Boolean) = (1, "2", true)
        println(tuple)
        println("-------------------------")

        // 访问数据
        // _i属性代表着元组中第i个元素
        println(tuple._1)
        // productElement(index),index是下标
        println(tuple.productElement(0))
        println("-------------------------")

        // 遍历元组数据
        for(elem <- tuple.productIterator) {
            println(elem)
        }

        // 嵌套元组
        val mulTuple = (1, 10, (1, 3, 5))
        println(mulTuple._3._1)
    }
}

7.集合常用函数

7.1 基本属性和常用操作

1)说明

(1)获取集合长度

(2)获取集合大小

(3)循环遍历

(4)迭代器

(5)生成字符串

(6)是否包含

2)案例

object Test_CommonOp {
    def main(args: Array[String]): Unit = {
        val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)

        //(1)获取集合长度
        println(list1.length)
        println("---------------------------")
        //(2)获取集合大小,等同于 length
        println(list1.size)
        println("---------------------------")
        //(3)循环遍历
        list1.foreach(println)
        println("---------------------------")
        //(4)迭代器
        for (elem <- list1.iterator) {
            println(elem)
        }
        println("---------------------------")
        //(5)生成字符串
        println(list1.mkString(","))
        println("---------------------------")
        //(6)是否包含
        println(list1.contains(3))
        println("---------------------------")
    }
}

7.2 衍生集合

1)说明

(1)获取集合的头

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

(3)集合最后一个数据

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

(5)反转

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

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

(8)并集

(9)交集

(10)差集

(11)拉链

(12)滑窗

2)案例

object Test_DerivedCollection {
    def main(args: Array[String]): Unit = {
        val list1 = List(1, 3, 5)
        val list2 = List(10, 13)

        //(1)获取集合的头
        println(list1.head)
        println("----------------------------")
        //(2)获取集合的尾(并非最后一个元素)
        println(list1.tail)
        println("----------------------------")
        //(3)集合最后一个数据
        println(list1.last)
        println("----------------------------")
        //(4)集合初始元素(即不包含最后一个元素的其他元素集合)
        println(list1.init)
        println("----------------------------")
        //(5)反转
        println(list1.reverse)
        println("----------------------------")
        //(6)取前(后)n 个元素
        println(list1.take(2))
        println(list1.takeRight(2))
        println("----------------------------")
        //(7)去掉前(后)n 个元素
        println(list1.drop(2))
        println(list1.dropRight(2))
        println("----------------------------")
        //(8)并集
        // 如果是用set去做并集,会自动去重
        println(list1.union(list2))
        println(list1 ::: list2)
        println("----------------------------")
        //(9)交集
        println(list1.intersect(list2))
        println("----------------------------")
        //(10)差集
        println(list1.diff(list2))
        println(list2.diff(list1))
        println("----------------------------")
        // (11)拉链(将两个集合对应位置元素配对,形成二元组,如果某个集合有多余的部分则会直接去掉)
        println(list1.zip(list2))
        println(list2.zip(list1))
        println("----------------------------")
        // (12)滑窗
        // 获取大小为2的滑动窗口
        // list1.sliding(2)得到的是一个迭代器(iterator)
        // 结果解释:(1, 3, 5) 获取一个大小为二的滑动窗口,初始即为(1, 3),进行滑动,即为(3, 5)
        // 若初始为(1, 3, 5, 10, 13),窗口大小为3,则结果应为(1, 3, 5),(3, 5, 10),(5, 10, 13)
        // 可以设置第二个参数步长,即为窗口一次滑动的距离
        for(elem <- list1.sliding(2)) {
            println(elem)
        }
    }
}

7.3 集合计算简单函数

1)说明

(1)求和

(2)求乘积

(3)最大值

(4)最小值

(5)排序

2)案例

object Test_SimpleFunction {
    def main(args: Array[String]): Unit = {
        val list: List[Int] = List(1, 3, 5, 10, 13)
        val list2 = List(("1", 1), ("2", 2), ("3", 3))

        //(1)求和
        println(list.sum)
        println("----------------------------")
        //(2)求乘积
        println(list.product)
        println("----------------------------")
        //(3)最大值
        // 如果集合内部存在元组类型,则只取第一个进行比较
        println(list.max)
        // 对具体情况进行处理再来寻找最大值
        // println(list2.maxBy((tuple: (String, Int)) => tuple._2))
        // 简写形式
        println(list2.maxBy(_._2))
        println("----------------------------")
        //(4)最小值
        println(list.min)
        println(list2.minBy(_._2))
        println("----------------------------")
        //(5)排序
        // 5.1 sorted
        println(list.sorted)
        // 从大到小逆序排列
        println(list.sorted.reverse)
        // 传入隐式参数
        println(list.sorted(Ordering[Int].reverse))
        println("----------------------------")
        // 5.2 sortBy
        println(list2.sorted)
        println(list2.sortBy(_._2))
        println(list2.sortBy(_._2)(Ordering[Int].reverse))
        println("----------------------------")
        // 5.3 sortWith
        // 从小到大排序
        // println(list.sortWith((x, y) => x < y))
        // 简写形式
        println(list.sortWith(_ < _))
        // 从大到小排序
        // println(list.sortWith((x, y) => x > y))
        println(list.sortWith(_>_))
        println("----------------------------")
    }
}

(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 Test_HighLevelFunction_Map {
    def main(args: Array[String]): Unit = {
        val list = List(1, 3, 5, 10, 13)

        // 过滤
        // 选取偶数
        // val evenList = list.filter(elem => elem % 2 == 0)
        val evenList = list.filter(_ % 2 == 0)
        println(evenList)
        // 选取奇数
        println(list.filter(_ % 2 == 1))
        println("----------------------------")

        // map映射
        // 将集合中每个数乘3
        println(list.map(_ * 3))
        println("----------------------------")

        // 扁平化
        val nestedList: List[List[Int]] = List(List(1, 3, 5), List(10, 13))

        val flatList = nestedList(0) ::: nestedList(1)
        println(flatList)

        val flatList2 = nestedList.flatten
        println(flatList2)
        println("----------------------------")

        // 扁平映射
        // 将一组字符串分词并保存为单词列表
        val strings: List[String] = List("hello scala", "hello spark", "hello java")
        val splitList: List[Array[String]] = strings.map(_.split(" "))
        val flattenList = splitList.flatten // 打散扁平化
        println(flattenList)

        val flatmapList = strings.flatMap(_.split(" "))
        println(flatmapList)
        println("----------------------------")

        // 分组groupBy
        // 分成奇偶两组
        val groupMap1: Map[String, List[Int]] = list.groupBy(data => {
            if(data % 2 == 0) "偶数" else "奇数"
        })
        println(groupMap1)
        // 简写形式
        val groupMap2: Map[Int, List[Int]] = list.groupBy(_ % 2)
        println(groupMap2)

        // 给定一组词汇,按单词首字母分组
        val wordList = List("china", "america", "test")
        println(wordList.groupBy(_.charAt(0)))
    }
}

3)集合转换操作(Reduce)

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

案例

object Test_HighLevelFunction_Reduce {
    def main(args: Array[String]): Unit = {
        val list = List(1, 3, 5)

        // reduce
        // reduce底层是调用了reduceLeft
        println(list.reduce(_ + _))
        // 从左往右
        println(list.reduceLeft(_ + _))
        // 从右往左
        println(list.reduceRight(_ + _))
        println("-----------------------------------")

        val list2 = List(10, 13)
        println(list2.reduce(_ - _))
        println(list2.reduceLeft(_ - _))
        // 看reduceRight源码,可发现reduceRight实际还是从左往右
        println(list2.reduceRight(_ - _)) // ( 10 - (13))
    }
}

4)Fold方法

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

案例

object Test_Fold {
    def main(args: Array[String]): Unit = {
        val list = List(1, 3, 5)
        val list2 = List(10, 13, 10)

        // fold
        println(list.fold(10)(_ + _)) // 10 + 1 + 3 + 5
        println(list.foldLeft(10)(_ - _)) // 10 - 1 - 3 - 5
        // 仍是由左往右减,但首先应该用最后一个值减去初始值,具体实现可见源码
        // (10, 13, 10),10 - (13 - (10 - 11)),-4
        println(list2.foldRight(11)(_ - _)) // 10 - (13 - 11)
    }
}

7.5 高级计算函数案例

合并Map

Map的合并会存在一种问题,例如map1 ++= map2,不存在的key会加入,但已存在的key会进行覆盖,在某些场

景下这样做反而不适用。

object Test_MergeMap {
    def main(args: Array[String]): Unit = {
        val map1 = mutable.Map("1" -> 1, "2" -> 2, "3" -> 3, "10" -> 1010, "13" -> 333)
        val map2 = Map("10" -> 10, "13" -> 13)

        // 在此处不能使用fold,只能使用foldLeft(map1与map2类型不同)
        val map3 = map2.foldLeft(map1) {
            (mergedMap, kv) => {
                val key = kv._1
                val value = kv._2
                mergedMap(key) = mergedMap.getOrElse(key, 0) + value
                mergedMap
            }
        }

        println(map3)
    }
}

7.6 普通WordCount案例

1)需求

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

2)需求分析

3)案例

object Test_CommonWordCount {
    def main(args: Array[String]): Unit = {
        val stringList: List[String] = List(
            "hello",
            "hello scala",
            "hello spark",
            "hello flink",
            "hello spark from scala"
        )

        // 对字符串进行切分,得到一个打散所有单词的列表
        // val wordList1: List[Array[String]] = stringList.map(_.split(" "))
        // val wordList2: List[String] = wordList1.flatten
        // println(wordList2)
        val wordList = stringList.flatMap(_.split(" "))
        println(wordList)
        println("-------------------------------")

        // 相同的单词进行分组
        val groupMap: Map[String, List[String]] = wordList.groupBy(word => word)
        println(groupMap)
        println("-------------------------------")

        // 对分组之后的List去长度来获取各个单词的个数
        val countMap: Map[String, Int] = groupMap.map(kv => (kv._1, kv._2.length))

        // 将map转为list,并排序取前三
        val sortList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)
        println(sortList)
    }
}

7.7 复杂WordCount案例

`object Test_ComplexWordCount {
    def main(args: Array[String]): Unit = {
        val tupleList: List[(String, Int)] = List(
            ("hello", 1),
            ("hello scala", 3),
            ("hello spark", 5),
            ("hello flink", 10),
            ("hello spark from scala", 13)
        )

        // 思路一:直接展开为普通版本
        val newStringList = tupleList.map(
            kv => {
                // 句子数目乘以数量,即包含了所有的词汇
                // 加一个空格是为了防止单词连在一起
                (kv._1.trim + " ") * kv._2
            }
        )
        println(newStringList)
        println("------------------------")

        // 之后操作与之前WordCount完全一致
        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)
        println("------------------------")

        // 思路二:直接基于预统计的结果进行转换
        // 将字符串打散成单词,并结合相应的个数包装成二元组
        val preCountList: List[(String, Int)] = tupleList.flatMap(
            tuple => {
                val strings: Array[String] = tuple._1.split(" ")
                strings.map(word => (word, tuple._2))
            }
        )
        println(preCountList)
        println("------------------------")

        // 对二元组按照单词进行分组
        val preCountMap: Map[String, List[(String, Int)]] = preCountList.groupBy(_._1)
        println(preCountMap)
        println("------------------------")

        // 叠加每个单词预统计的个数值
        val countMap: Map[String, Int] = preCountMap.mapValues(
            tupleList => tupleList.map(_._2).sum
        )
        println(countMap)
        println("------------------------")

        // 转换成List,排序取前三
        val countList: List[(String, Int)] = countMap.toList.sortWith(_._2 > _._2).take(3)
        println(countList)
    }
}

8.队列

1)说明

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

dequeue。

2)案例

object Test_Queue {
    def main(args: Array[String]): Unit = {
        // 创建一个可变队列
        val queue: mutable.Queue[String] = new mutable.Queue[String]()

        // 入队方法没有返回值(即返回值为空)
        queue.enqueue("a", "b", "c")
        println(queue)

        // 出队方法有返回值,返回值为出队的元素
        println(queue.dequeue())
        println(queue)

        // 不可变队列
        // 不可变队列本身不可改变
        val queue2 = Queue("a", "b", "c")
        val queue3 = queue2.enqueue("e")
        println(queue3)
    }
}

9.并行集合

1)说明

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

2)案例

object Test_Parallel {
    def main(args: Array[String]): Unit = {
        val result: immutable.IndexedSeq[Long] = (1 to 100).map(
            x => Thread.currentThread.getId
        )
        println(result)

        // 有很多不同线程在执行,故结果与前者不同
        val result2: ParSeq[Long] = (1 to 100).par.map(
            x => Thread.currentThread.getId
        )
        println(result2)
    }
}
Scala学习七之集合了解 Scala有一个非常通用,丰富,强大,可组合的集合库;集合是高阶的(high level)并暴露了一大套操作方法。 Scala的所有的集合类都可以在包 scala.collection 包中找到,其中集合类都是高级抽象类或特性 Iterable[T] 是所有可遍历的集合,它提供了迭代的方法(foreach)。Seq[T] 是有序集合,Set[T]是数学上的集合(无序且不重复),Map[T]是关联数组,也是无序的。 Scala 集合类系统地区分了可变的和不可变的集合。 可变集合可以在适当的地方被更 阅读详情

相关推荐

ESP32-S3双模CMSIS-DAP调试器:USB+WiFi无线调试方案

CMSIS-DAP是ARM生态中标准化的嵌入式调试协议接口,广泛用于Keil、IAR、STM32CubeIDE等开发环境。其核心原理是通过SWD/JTAG物理层实现目标芯片寄存器访问、内存读写与断点控制,依赖确定性时序和低延迟通信。传统DAPLink调试器受限于USB线缆束缚,而WiFi-USB-DAPLink项目将完整CMSIS-DAP v2协议栈移植至ESP32-S3平台,同时支持USB CDC直连与WiFi TCP远程通道,兼顾实时性与网络化部署能力。该方案无需主机驱动、兼容主流IDE,并支持多机并发

weixin_31185473的博客 368

scala_集合专题

第 7 章 集合 7.1 集合简介 1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable 特质。 2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两 个包 不可变集合:scala.collection.immutable 可变集合: scala.collection.mutable 3)Scala 不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而 不会对原对象进行修改。类似于 java 中的 Str

niuyan666的博客 420

esp32-C3固件烧录用户手册

温馨提示:1.esp32-C3 BOOT脚为GPIO9,需要从芯片小板中焊接引出2.芯片小板中已经预留了所有烧录相关的引脚,大家可以按需焊接引线3.程序下载完,使用串口查看log时,需要使用220v供电使用(请务必准守用电安全)。原因:由于插座中包含继电器,计量计等耗电设备,所以usb转串口提供的3.3V电压和电流可能会出现供电不足,表现为usb转串口与电脑连接断断续续,导致无法查看log。

hbwang的博客 1万+

第1节 Scala基础语法:13、list集合的定义和操作;16、set集合;17、map集合

list.+:5 , list.::5: 在list集合头部添加单个元素5 ; li1.:+(5):在list集合尾部添加单个元素5; li1++li2,li1:::li2:在li1集合尾部添加il2集合; li1.:::(li2):在li1集合头部添加li2集合。 li1--=li2:可变list集合li1中,减去li2集合中的元素,li1中的元素为减少后的元素。 Li...

dengmanzhou3124的博客 371

大连海事大学课设题目/基于LM331的频率电压转换器

部分基于LM331的频压转换的实物连接问题

2301_76649592的博客 3226

RK3588 C-PHY摄像头驱动升级踩坑记:从‘Only CSI2 supported’报错到成功取流

本文详细记录了在RK3588平台上调试C-PHY摄像头驱动的全过程,从‘Only CSI2 supported’报错分析到成功取流。内容涵盖C-PHY与CSI-2协议差异、SDK版本对比、V4L2框架下的bus-type解析机制,以及硬件排查与寄存器调优实战经验,为嵌入式Camera驱动工程师提供宝贵参考。

weixin_42522374的博客 123

Scala——集合

Scala——集合7 集合7.1 集合简介7.2 数组7.3 列表List7.4 Set集合7.5 Map集合7.6 元组7.7 集合常用函数7.8 队列7.9 并行集合 7 集合 7.1 集合简介 集合简介: (1)Scala 的集合有三大类:序列 Seq、集 Set、映射 Map,所有的集合都扩展自 Iterable特质。 (2)对于几乎所有的集合类,Scala 都同时提供了可变和不可变的版本,分别位于以下两个包 不可变集合:scala.collection.immutable 可变集合: scala.

qq_42873479的博客 3282

【AI 编程工具进阶用法】如何在Cursor、Trae等工具中使用Skills

OpenSkills是一个开源项目,用于在Cursor、Trae等AI编程工具中添加可复用、可组合的"能力模块"。安装流程包括:1)全局安装OpenSkills CLI工具;2)选择安装Anthropic官方Skills到项目或全局;3)创建AGENTS.md文件同步Skills;4)在AI工具中调用Skills。此外还介绍了UI/UX Pro Max Skill项目,通过npm安装后可为AI添加设计能力。这些Skills相当于为AI工具安装"高级技能包"

肌肉金轮的博客 3543

(7)scala 集合定义 & 常用方法

集合定义: Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包 可变集合可以在适当的地方被更新或扩展。这意味着你可以修改,添加,移除一个集合的元素。 不可变集合类,相比之下,永远不会改变。不过,你仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。 ...

qq_41123269的博客 494

KUKA机器人修改机器人名称和IP地址的具体方法示例

KUKA机器人修改机器人名称和IP地址的具体方法示例

Robot_PLC_HMI_Automation 5259

ISO13849功能安全从入门到精通(3):安全功能及其对降低风险的贡献4

例如,如果机器必须在有限速度下运行时进行设置,那么在低加速度值下进行设置时,参数P1将是正确的选择:随着危险缓慢出现并给予足够的运动自由,操作员将能够移出危险区域。例如,在无故障的条件下,在操作者的手的方向移动的滚子不能陷住它。在所有其他情况下,F1是正确的选择,前提是危险暴露的持续时间不超过机器总操作时间的1/20。需求来源于必要的风险降低。由于这些考虑而降低的PLr在任何情况下都不得低于通过比较方式考虑的机器的PLr,因为并不能从事故发生率低和严重程度低得出实施的安全功能提供的安全水平高于要求。

wdconan001的博客 834

Scala-集合

1、空集合Nil,以及右结合 object controllAbstract { def main(args: Array[String]): Unit = { //向空集合Nil中添加元素 //双冒号是右结合 // println((1::2::Nil)); //List(1, 2) val li...

weixin_30925411的博客 162

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Scala 高阶(七):集合内容汇总(上篇)

在JavaList集合、Set集合、Map集合。其中List集合、Set集合继承自Collection。它们都是接口。Scala的集合有三大类序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。、可变集合s不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象。可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象和就是j。...

我这么骄傲的一个人。 5029

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

scala学习七:集合

Scala提供了一套很好的集合实现,提供了一些集合类型的抽象。Scala 集合分为可变的和不可变的集合。可变集合可以在适当的地方被更新或扩展。可以修改,添加,移除一个集合的元素。而不可变集合类,永远不会改变。不过,仍然可以模拟添加,移除或更新操作。但是这些操作将在每一种情况下都返回一个新的集合,同时使原来的集合不发生改变。

eight_Jessen的博客 1261

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Scala集合

一、集合的简介 1)Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。 2)对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包 不可变集合:scala.collection.immutable 可变集合:scala.collection.mutable 3)Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象 4)可变集合,就是这个集

Markble 6538

Scala(七)之 集合

文章目录7.集合7.1 集合简介7.1.1 不可变集合继承图7.1.2 可变集合继承图7.2 数组7.2.1 不可变数组7.2.2 可变数组7.2.3 不可变数组与可变数组的转换7.2.4 多维数组7.3 Seq集合(List)7.3.1 不可变List7.3.2 可变ListBuffer7.4 Set集合7.4.1 不可变Set7.4.2 可变mutable.Set7.5 Map集合7.5.1 不可变Map7.5.2 可变Map7.6 元组7.7 集合常用函数7.7.1 基本属性和常用操作7.7.2 衍生

子清的博客 360

Scala之集合(2)

按照单词出现的次数排序:这样是需要自定义的 调用sortBy()函数(By---什么方式)设置返回类型就是按照什么排序(匿名函数)按照单词出现的次数反转排序:通过sortBy()源码可知他是采用了柯里化写法(闭包---把上层变量定义成常量传给下一层)上述代码在第一次传入参数返回的是以Int类型的集合 在对他进行封装成常量传递给下层 所以 在柯里化的第二个()的时候在设置类型的时候要设置Int类型。

&volume的博客 1866

scala List集合的用法

一、前言: 人们常说,Scala是一个难掌握的语言,一是其面向函数和面向对象结合的原因,二是其丰富的语法和内置函数。 对于Conllection 这一章的内容,更多的是利用内置函数灵活地运用,避免自己重复造轮子(要求性能高除外) 对于集合,通常来说有以下几个常用操作是必须掌握的: 1.增删改查单个元素 2.单个集合的各种遍历方式 3.单个集合分拆组合与翻转

残缺的歌的专栏 4万+

Scala 高阶(七):集合内容汇总(上篇)_scala内容集合表

在JavaList集合、Set集合、Map集合。其中List集合、Set集合继承自Collection。它们都是接口。Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。、可变集合: s不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于 java 中的 String 对象。可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于 java 中 StringBuilder 对象。

2401_85015220的博客 999

Scala学习之(七)集合

文章目录 ​​​​​ 一、集合简介 1、不可变集合继承图 2、可变集合继承图 二、数组 1.不可变数组 2.可变数组 3、不可变数组与可变数组的转换 4、多维数组 三、Seq集合(List) 1、不可变List 四、set集合 1、不可变set 2、可变mutable.Set 五、Map集合 1、不可变Map 2、可变Map 六、元组 七、集合常用函数 1、基本属性和常用操作 3、集合计算初级函数 4、集合计算高级函数 5、普通wordcount案例 6、复

goTsHgo的博客 459

map集合遍历_Scala学习七之集合了解

Scala有一个非常通用,丰富,强大,可组合的集合库;集合是高阶的(high level)并暴露了一大套操作方法。Scala的所有的集合类都可以在包 scala.collection 包中找到,其中集合类都是高级抽象类或特性Iterable[T] 是所有可遍历的集合,它提供了迭代的方法(foreach)。Seq[T] 是有序集合,Set[T]是数学上的集合(无序且不重复),Map[T]是关联数组,...

weixin_39710179的博客 539

【Scala入门】掌握Scala集合:列表、数组与集合操作

集合(Collection)在编程中扮演着至关重要的角色。Scala 提供了丰富且强大的集合库,支持多种集合类型和操作。本文将介绍 Scala 中的常用集合类型,包括列表(List)、数组(Array)以及其他集合类型,并详细讲解如何操作这些集合。

weixin_52938153的博客 1126

Scala从入门到精通04之集合

1. 集合简介 2. 数组 3. 列表List 4. Set集合 5. Map集合 6. 元祖 7. 集合常用函数 8. 队列 9. 并行集合

weixin_46036165的博客 2883

Scala集合入门学习

遍历集合可以使用迭代器iterator的那套迭代方式。Seq是一个有先后次序的序列,比如数组或列表。IndexedSeq可以通过下标进行任意元素的访问。例如ArrrayBuffer。 Set是一组没有先后次序的值,在SortedSet中,元素以某种排过序的顺序被访问。 Map是一组(键,值)对偶,SortedMap按照键的顺序访问实体 Scala集合有三个基本操作: head 返回集合第一个元素...

GalenGao 487
上一篇: Scala入门(六)面向对象
下一篇: Web前端入门(一)初识WEB
Silver  Star
Silver Star 新星创作者: 大数据技术领域 新星创作者: 大数据技术领域
博客等级 码龄7年 1万+粉丝 72原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Silver Star

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值