首页 > 其他分享 >大数据学习15之Scala集合与泛型

大数据学习15之Scala集合与泛型

时间:2024-11-15 19:43:32浏览次数:3  
标签:15 val Scala 元素 集合 泛型 println Array

1. 概述

        大部分编程语言都提供了数据结构对应的编程库,并称之为集合库(Collection Library),Scala 也不例外,且它还拥有以下优点:
易用:灵活组合运用集合库提供的方法,可以解决大部分集合问题
简洁:拜类型推断和函数式编程所赐,帮助程序员写出更简洁,更优雅的代码
安全:绝大部分错误都可以在编译期被发现
快速:集合类型的方法在实现时,都进行了调优,用户可以根据需求选择合适的集合
统一:Scala 的集合有非常严谨的继承体系,相似类型的集合拥有同样的一组方法,当然也有属于自己独有的方法。

2. 分类

        不可变集合:集合内的元素、长度一旦初始化完成就不可再进行更改,任何对集合的改变都将生成一个新的集合。不可变集合都在 scala.collection.immutable 这个包下,使用时无需手动导包。

        可变集合    :指的是这个集合本身可以动态改变,且可变集合提供了改变集合内元素的方法。可变集合都在scala.collection.mutable 这个包下,使用时需要手动导包。

3. 继承树

        

4. 上层接口

4.1. Traversable

4.1.1. 概述

        Traversable 是一个特质(trait),它是其他集合的父特质,它的子特质 immutable.Traversable 和 mutable.Traversable 分别是不可变集可变集合的父特质,集合中大部分通用的方法都是在这个特质中定义的。因此了解它的功能对学习其他集合类十分重要。

4.1.2转置集合

了解过线性代数的同学都知道,矩阵有一个转置的操作,在 Scala 中,可以轻松通过 transpose() 方法实现类似的效果。矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引,如下图:

4.1.3. 拼接集合

        新集合=集合1++集合2 

        会创建临时集合,不推荐

        新集合=Traversable.concat(集合1, 集合2, 集合3)

        预先计算所需集合大小,生成一个集合,减少临时集合的生成。

4.1.4. 计算阶乘*

        

4.1.5. 获取元素*

4.1.6. 判断元素*

4.1.7. 聚合操作

4.1.8. 类型转换

        有时候,需要把 Traversable 集合转换成其他的集合来进行操作,例如转为 Set 集快速去重,此时就需要用到toXxx() 方法(toList, toSet, toArray, toSeq 等)。

4.1.9. 填充元素

        

4.2. Iterable

4.2.1. 概述

        Iterable 代表一个可以迭代的集合,它继承了 Traversable 特质,同时也是其他集合的父特质。最重要的是,它定义了获取迭代器 iterator 的方法: def iterator: Iterator[A] ,这是一个抽象方法,它的实现类需要实现这个方法,从而实现迭代集合并返回集合中的元素。

4.2.2. 分类

        iterator()

        foreach()

4.2.3. 遍历集合

    list.foreach(println);


    it=list.toIterator();
    while(it.hasNext()){
        println(it.next())
}

4.2.4. 分组遍历

object IterableGroupedDemo {
def main(args: Array[String]): Unit = {
// 定义一个 Iterable 集合,存储 1~13 之间的所有整数
val iterable = (1 to 13).toIterable
// 通过 grouped() 方法,对 Iterator 集合按照 5 个元素为一组的形式进行分组,遍历并打印结果
val iterator = iterable.grouped(5)
while (iterator.hasNext) {
println(iterator.next())
}
}

4.2.5. 按索引生成元组

/**
* 按索引生成元组
*/
object IterableGenerateTupleDemo {
def main(args: Array[String]): Unit = {
// 定义一个 Iterable 集合,存储"A", "B", "C", "D", "E"
val i = Iterable("A", "B", "C", "D", "E")
// 通过 zipWithIndex() 方法按照`字符串 -> 索引`生成新的集合
val result1 = i.zipWithIndex
println(s"result1 = ${result1}")
// 通过 map() 方法按照`索引 -> 字符串`生成新的集合
val result2 = result1.map(x => x._2 -> x._1)
println(s"result2} = ${result2}")
}
}

4.2.6. 判断集合是否相同

        通过 sameElements() 方法来实现该需求。

4.3. Seq

4.3.1. 概述

        Seq(Sequence)特质代表按照一定顺序排列的元素序列,序列是一种特别的可迭代集合,它的元素特点是有序(元素存取顺序一致),可重复,有索引。

4.3.2. 分类

        

4.3.3. 获取元素与长度

object SeqGetElementAndLenDemo {
def main(args: Array[String]): Unit = {
// 创建 Seq 集合,存储元素 1, 2, 3, 4, 5
val s = (1 to 5).toSeq
// 打印集合元素
s.foreach(x => println(x))
// 简化版
s.foreach(println(_))
s.foreach(println)
// 打印集合长度
println(s.size)
// 获取索引为 2 的元素
// 通过集合名(索引)的方式获取
println(s(2))
// 通过集合伴生对象的 apply 方法获取
println(s.apply(2))
}
}

4.3.4. 获取元素索引*

4.3.5. 判断集合是否包含指定元素

4.3.6. 修改元素

        

        

4.4. Set

去重;

HashSet 唯一无序;

ListSet 唯一有序(添加顺序);

TreeSet 唯一有序(自然顺序);

4.5. Map

HashMap:元素特点 Key 唯一、无序。
ListMap:元素特点 Key 唯一、有序(元素添加的顺序)。
TreeMap:元素特点 Key 唯一、排序(按自然顺序排序)。

5. 下层实现

  敲代码练习

数组 Array

元组 Tuple

列表 List

集 Set

映射 Map

迭代器 Iterator

栈 Stack

队列 Queue

6. 函数式编程

        函数式编程将计算视为数学函数的求值,强调纯函数、不可变性和高阶函数的使用。函数式编程的核心思想是将计算任务分解为函数之间的组合,以解决问题和构建软件。

内容另起;

泛型 Generics

1. 分类

1.1. 泛型集合

        

// 定义集合不指定泛型,可以随意存储sca
val list1 = List(2, 3.14, "abc", true, null)
// 定义集合指定泛型,只能存储指定类型数据
val list2 = List[Int](1, 2, 3, 4, 5)

1.2. 泛型方法

def 方法名[泛型名称](...): Unit {
}

1.3. 泛型类

/**
* 泛型类
*/
object GenericsClassDemo {
// 定义一个 Pair 泛型类,该类包含两个字段,且两个字段的类型不固定
class Pair[T](var a: T, var b: T)
case class Person(name: String, age: Int)
def main(args: Array[String]): Unit = {
// 创建不同类型的 Pair 泛型类对象,并打印
val pair1 = new Pair[Int](10, 20)
println(pair1.a, pair1.b)
val pair2 = new Pair[Person](Person("张三", 18), Person("李四", 19))
println(pair2.a, pair2.b)
}
}

1.4. 泛型特质

/**
* 泛型特质
*/
object GenericsTraitDemo {
// 定义泛型特质 Logger,该特质有一个变量 name 和 log 方法,它们都使用 Logger 特质的泛型
trait Logger[T] {
val name: T
def log(b: T)
}
// 定义单例对象 InfoLogger 继承 Logger 特质
object InfoLogger extends Logger[String] {
override val name: String = "INFO"
override def log(b: String): Unit = println(b)
}
def main(args: Array[String]): Unit = {
InfoLogger.log(s"${InfoLogger.name}:这是一条日志信息")
}
}

2. 上下界

2.1. 上界

        使用 T <: 类型 表示给类型添加一个上界,表示泛型参数必须是继承自该类型或是其类型本身。
        例如: [T <: Animal] 表示泛型 T 的数据类型必须是 Animal 类型或者 Animal 的子类型。

/**
* 上界
*/
object GenericsUpDemo {
// 定义一个 Animal 类
class Animal
// 定义一个 Cat 类,继承 Animal 类
class Cat extends Animal
// 定义一个 Tom 类,继承 Cat 类
class Tom extends Cat
// 定义一个泛型方法 demo,该方法接收一个 Array 参数
// 限定 demo 方法的 Array 元素类型只能是 Animal 或者 Animal 的子类型
def demo[T <: Cat](arr: Array[T]): Unit = {
println(arr.mkString("Array(", ", ", ")"))
}
def main(args: Array[String]): Unit = {
// 测试调用 demo 方法,传入不同元素类型的 Array
// 定义上界以后,下面这行代码会报错
//demo(Array(new Animal, new Animal))
demo(Array(new Cat, new Cat))
demo(Array(new Tom, new Tom))
}
}

2.2. 下界

        使用 T >: 类型 表示给类型添加一个下界,表示泛型参数必须是该类型的祖先类或是其类型本身。
        例如: [T >: Person] 表示泛型 T 的数据类型必须是 Person 类型或者 Person 的祖先类型。

/**
* 下界
*/
object GenericsDownDemo {
// 定义一个 Animal 类
class Animal
// 定义一个 Cat 类,继承 Animal 类
class Cat extends Animal
// 定义一个 Tom 类,继承 Cat 类
class Tom extends Cat
// 定义一个 demo 泛型方法,该方法接收一个 Array 参数
// 限定 demo 方法的 Array 元素类型只能是 Person 或者 Hero
def demo[T >: Cat](arr: Array[T]): Unit = {
println(arr.mkString("Array(", ", ", ")"))
}
def main(args: Array[String]): Unit = {
// 测试调用 demo 方法,传入不同元素类型的 Array
demo(Array(new Animal, new Animal))
demo(Array(new Cat, new Cat))
// 定义下界以后,下面这行代码会报错
//demo(Array(new Tom, new Tom))
}
}

3. 非变、协变、逆变

Spark 源代码中大量使用了协变、逆变、非变,学习该知识点对将来阅读 Spark 源码很有帮助。
非变:A 类和 B 类之间存在父子关系,泛型非变操作后两个泛型类之间不会产生任何关系。
协变:A 类和 B 类之间存在父子关系,泛型协变操作后两个泛型类之间也属于父子关系。
逆变:A 类和 B 类之间存在父子关系,泛型逆变操作后两个泛型类之间关系进行颠倒。

3.1. 语法格式

非变: Temp[T]{} 。泛型默认即是非变的。
协变: Temp[+T]{} 。
逆变: Temp[-T]{} 。

/**
* 非变、协变、逆变
*/
object GenericsVariantDemo {
class A
class B extends A
// 非变
class Temp1[T]
// 协变
class Temp2[+T]
// 逆变
class Temp3[-T]
def main(args: Array[String]): Unit = {
// 测试非变
val t1: Temp1[B] = new Temp1[B]
// 编译报错,非变操作后两个类之间不会产生任何关系
//val t2: Temp1[A] = t1
// 测试协变
val t3: Temp2[B] = new Temp2[B]
// 正常编译且运行,协变操作后两个类之间关系不发生任何改变
val t4: Temp2[A] = t3
// 测试逆变
val t5: Temp3[B] = new Temp3[B]
// 编译报错,逆变操作后两个类之间关系进行颠倒
//val t6: Temp3[A] = t5
// 以下逆变操作正常编译且运行
val t7: Temp3[A] = new Temp3[A]
val t8: Temp3[B] = t7
}
}

标签:15,val,Scala,元素,集合,泛型,println,Array
From: https://blog.csdn.net/qq_64407249/article/details/143803604

相关文章

  • SS241115C. 排序(sort)
    SS241115C.排序(sort)题意给你一个长度为\(n\)的序列\(a\),每次操作对\([1,\frac{n}{2}],[\frac{n}{2}+1,n]\)进行归并排序。有\(q\)次询问,给出\(t,x\),问进行\(t\)次操作后\(a_x\)的值。思路考虑一次操作发生了什么。假设\(x<y\),那么\(x\)和它后面的一坨都会排......
  • Android15音频进阶之input调节CarAudioService音量过程(九十四)
    简介:CSDN博客专家、《Android系统多媒体进阶实战》一书作者新书发布:《Android系统多媒体进阶实战》......
  • 比赛讲解:图论算法(11.11~11.15)
    图论算法T1-U502532找水杯一道水题,基本上和P4779一样(我连样例都搬过来了,能不一样吗?)所以呢,你们可以直接用\(Dijikstra\)1.最初起点到达所有点的距离都是未知的,记作无穷大。2.在对起点的邻接点进行扫描后发现,起点可以通过某些边抵达一些节点,那么就更新d数组(d[i]用于记录起点s......
  • 2024.11.15 test
    A一个\(n\timesm\)的矩形已经给出了\(k\)个位置的数,判断是否有方案使得填入非负整数后,每一个\(2\times2\)的子矩形都满足左上+右下=左下+右上。\(n,m,k\le1e5\)。注意到,矩形合法的条件可以转化为对于任意相邻的两列,在每行中,这两列值的差都相同。也就是对于所有行的每......
  • 11.15随笔
    这里是11.15随笔。前两天玩的有点欢,忘写随笔了。作业留档:有两张非递增有序的线性表A,B,采用顺序存储结构,两张表合并用c表存,要求C为非递减有序的,然后删除C表中值相同的多余元素。元素类型为整型输入格式:第一行输入输入表A的各个元素,以-1结束,中间用空格分隔;第二行输入表B的各个元......
  • 深入理解 MySQL 大小写敏感性:配置、问题与实践指南20241115
    深入理解MySQL大小写敏感性:配置、问题与实践指南在开发和部署MySQL数据库时,表名的大小写敏感性问题常常被忽略,却可能在跨平台迁移、团队协作或工具兼容性方面引发复杂的故障。本文将结合实际案例,深入探讨MySQL的lower_case_table_names参数,剖析其行为、配置方法以......
  • 列表数据隔离--采购申请单只能看当前用户的单据信息 过滤,PrepareFilterParameter 2
    region<<版本注释>>/*===================================================类名称:PUR_Requisition_listFilter类描述:列表数据隔离--采购申请单只能看当前用户的单据信息过滤,PrepareFilterParameter创建人:luohong创建时间:2024/11/1516:18:04电子邮箱:it_lu......
  • 2024.11.15 NOIP 模拟 - 模拟赛记录
    返乡(home)不给大样例是怕我找规律出答案吗?但是我还是找到规律了。题解说是结论题,但是这个结论即使观察小样例也很好猜(如果我是出题人就把样例打乱一下顺序)。首先考虑只有二维偏序时的最优放置方法:首先第一个数是不能重复的,因为一旦重复,第二个数无论怎么选,都会构成偏序;第二个......
  • 241115 noip 模拟赛
    省流:\(90+100+25+10\)。T1题意:给定一个长为\(n\)的排列,定义一次操作为选出排列中至多\(4\)个不同的数,将它们任意重排,求最少操作次数让这个排列单调递增。\(n\leq10^6\)。找出排列的所有置换环,设环长为\(t_1,t_2,t_3,\cdots,t_m\),则答案为:\[\sum_{i=1}^m\lflo......
  • [2024.11.15]NOIP 模拟赛
    赛后的思路永远比赛时清晰。赛时T1玩了一会发现\(a_3\sima_7\)一定是相邻的,所以只需要考虑两个数字即可。答案显然有单调性,所以考虑先二分\(a_2\),再二分\(a_1\)。两个二分的思路都很简单,第二个二分用lower_bound即可。第一个的话其实就是模拟lower_bound内置,赛时调......