大数据实时处理 1.6 Scala数据结构

文章详细介绍了Scala中的各种集合类型,包括定长与变长数组、不可变与可变列表、不可变与可变映射、元组以及集合的基本操作,如定义、遍历、添加、删除、合并、排序等,并提供了课堂练习和课后作业,帮助读者深入理解和掌握Scala集合框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、数组 (Array)

(一)定长数组

1、数组定义

(2)定义时指定数组长度,后赋值

2、数组遍历

(1)传统for循环方式

(2)增强for循环方式

(3)利用foreach算子遍历数组

课堂练习:数组求和

3、常用方法

(1)求数组中数值总和

(2)求数组中的最大值

(3)求数组中的最小值

(4)对数组实现升序

(5)对数组实现降序

课堂练习:数组查询

(二)变长数组

1、数组定义

2、遍历数组

3、移除元素

4、数组合并

5、插入元素

二、列表 (List)

(一)不可变列表

1、创建不可变列表

2、给列表添加元素

3、列表合并操作

4、二维列表

(二)可变列表

1、创建可变列表

2、列表合并

3、列表排序

4、列表总和、平均值、最值

5、添加新元素

6、移除列表元素

三、映射 (Map)

(一)不可变映射

1、创建不可变映射

2、遍历不可变映射

(二)可变映射

1、创建可变映射

2、修改可变映射

3、查询可变映射

4、添加元素

5、删除元素

四、元组 (Tuple)

(一)定义元组

1、直接赋值定义元组

2、创建指定长度的元组

(二)访问元组

(三)迭代元组

(四)元组转为字符串

课堂练习:对一个字符串进行词频统计

方法一

方法二

方法三

五、集合 (Set)

(一)定义集合

(二)增减元素

(三)集合方法

1、获取首元素

2、获取去首子集合

课堂练习:删除排前的三个城市

3、两个集合求并集

4、两个集合求交集

5、求集合的最值

6、求集合的总和和平均值

7、集合的遍历

六、课后作业

任务:IP地址去重


Scala集合(collection)分为可变集合(mutable collection)和不可变集合(immutable collection)。可变集合可以对其中的元素进行修改、添加、移除;而不可变集合永远不会改变,但是仍然可以模拟添加、移除或更新操作。这些操作都会返回一个新的集合,原集合的内容不发生改变。

一、数组 (Array)

  • Scala中的数组分为定长数组和变长数组,定长数组初始化后不可对数组长度进行修改,而变长数组则可以修改。

(一)定长数组

在这里插入图片描述

1、数组定义

(1)定义数组时初始化数据

  • 自动推断数组类型

  • 手动指定数据类型

(2)定义时指定数组长度,后赋值

  • 先定义,后赋值

  • 避免数组下标越界错误

2、数组遍历

  • 定义数组arr(自动推断类型,静态初始化)

  • 可以使用for循环对数组进行遍历,输出数组所有的元素

(1)传统for循环方式

  • 通过数组下标来遍历数组元素

  • 大家可以看到,反向遍历没有输出结果,怎么解决这个问题?

  • 参考一下Java正向和反向遍历数组,看能否得到启发

 在这里插入图片描述

  • 通过arr.length - 1 to 0 by -1实现反向遍历 

  • 说明:num1 to num2 by 1 相当于 num1 to num2

(2)增强for循环方式

  • 正向遍历数组元素

  • 反向遍历数组元素

(3)利用foreach算子遍历数组

  • 联想Java里列表的forEach()方法结合Lambda表达式

 在这里插入图片描述

  •  利用Scala的foreach算子来遍历数组

课堂练习:数组求和

  • 采用遍历算子

  • 采用增强for循环 

 

  • 课堂练习:采用传统for循环来求和

3、常用方法

  • Scala对数组提供了很多常用的方法,使用起来非常方便
  • 定义数组arr(通过数组类的构造方法来初始化数组,静态初始化)

 

  • 对数组arr也可以采用先定义后赋值的方式(动态初始化)

(1)求数组中数值总和

  • 调用sum方法

  • 其实,还可以调用归并算子来求和

(2)求数组中的最大值

  • 调用max方法

(3)求数组中的最小值

  • 调用min方法,也可以自己编写代码求最小值

(4)对数组实现升序

  • 调用sorted方法

 

  • 不可变数组调用sorted方法之后会产生一个新的排序数组,而原来的数组保持不变
  • 联想一下SQL语句如何实现表记录的排序:SELECT * FROM t_student WHERE gender = '男' ORDER BY age ASC

(5)对数组实现降序

  • 先调用sorted方法升序,再调用reverse方法反序,就可以实现数组降序

  • 4,5总结

  • 联想一下SQL语句如何实现表记录的排序:SELECT * FROM t_student WHERE gender = '男' ORDER BY age DESC;
  • 试一试,Python列表如何实现升序和降序

在这里插入图片描述

  • Python列表的sort()方法是直接在原列表上进行排序


在这里插入图片描述

  • Python的内置函数sorted()不会改动原列表,会产生一个排序的新列表

课堂练习:数组查询

  • 定义一个整型数组,输入一个整数,判断该整数是否在数组里,如果在数组里,给出其位置,否则提示用户该整数不在数组里。

  • day03包里创建Exercise01对象

package day03

import scala.io.StdIn

/**
 * 功能:列表查询
 * 作者:柠檬
 * 日期:2023年03月13日
 */
object Exercise01 {
  def main(args: Array[String]): Unit = {
    val arr = Array(4, 5, 8, 12, 30, 8, 45, 18)
    for (x <- arr) print(x.toString + " ")
    println()
    print("x=")
    val x = StdIn.readInt()
    if (arr.contains(x)){
    for( i <- 0 until arr.length){
      if (x == arr(i))
        println("arr(" + i +")=" + x )
    }
      }else{
      println(x.toString + "不在数组里~")
    }
  }
}
  • 运行结果 

 

  • 用Python语言按同样的思路来编写程序

在这里插入图片描述

  • 用Java语言按同样的思路来编写程序 

在这里插入图片描述

  • 直接遍历输出等于查询目标的数组元素,统计统计满足条件的个数,如果个数等于零,说明查询目标不在数组里

  • day03包里创建Exercise01_对象

 在这里插入图片描述

  • 运行程序 

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 课堂练习:用多种方法编程将字符串“internationalization”(i18n)中的“a”全部找出来,并给出相应的位置。

(二)变长数组

在这里插入图片描述

1、数组定义

  • 变长数组使用类scala.collection.mutable.ArrayBuffer进行定义
  • 定义一个变长Int类型数组arr,利用+=运算符、append方法添加一个数组元素(注意是追加元素),还可以利用appendAll方法添加一个数组(多个元素)

2、遍历数组

  • 遍历数组arr,跟遍历定长数组没有不同

3、移除元素

  • 利用remove方法可以按下标删除数组元素,当然可能出现下标越界异常 

  • 利用-=运算符按值直接删除数组元素

  • 数组中有多个值为2的元素,则从前向后删除第一个匹配的元素,本次删除,第一个2被删除了,但是第二2还依然存在。
  • 下面继续删除2(删除完2之后,继续删除,不会报错,正所谓以不变应万变) 

  • 使用remove()方法还可以在数组的固定位置移除指定数量的元素

  • 从数组arr的下标为2的位置开始移除3个元素

  • 如果移除起始位置 + 删除数量 > 数组长度,那么就会报错

4、数组合并

  • Scala支持使用++=符号将两个变长数组进行合并,其实还可以用appendAll方法来拼接两个数组
  • 定义三个变长数组arr1、arr2与arr3arr1采用++=合并arr2得到result,其实result与合并后的arr1是相等的,然后arr1再利用appendAll方法合并arr3,结果是三个数组的9个元素全部合并进数组arr1

5、插入元素

  • 使用insert()方法可以在数组指定位置插入一个元素,做法跟Python王权一样,第一个参数是下标(index),第二个参数是要插入的数据(value)

  • 在数组arr1的下标为2的位置插入一个元素666

  •  注意:一次插入多个元素是要报错的,插入一个数组还是要报错

  •  如果插入的位置参数超出数组的长度,要报错

  • 这个跟Python不同,插入的位置参数超出数组的长度,就直接在末尾添加新元素

在这里插入图片描述

  •  如果插入的位置参数等于数组长度,那么就相当于在末尾追加新元素

课堂练习:产生随机整数构成的变长数组

  • 产生一个变长数组,包含10个[a, b] (a∈ N \in N∈N, b∈ N \in N∈N, a < \lt< b)之间的随机整数

  • 三种方式来产生10个100以内的随机整数构成的变长数组(+=、append、insert)

二、列表 (List)

  • Scala中的列表分为可变列表和不可变列表,默认使用的列表为不可变列表。不可变列表也可以增加元素,但实际上生成了一个新列表,原列表不变。列表元素类型可以相同,也可以不一致。

(一)不可变列表

1、创建不可变列表

  • 创建列表有静态初始化和动态初始化两种方式
  • 创建一个Int类型的列表- list1

  • 创建一个混合类型的列表 - list2,元素类型被系统统一为Any 

 

  • 创建一个空列表,后面再添加元素

2、给列表添加元素

(1)在列表头添加元素

  • 利用.+:在列表头添加新元素
  • 在列表list1的头部追加一个元素0,生成一个新列表 list3,列表list1没有变的

 

  • 利用::在列表头添加新元素

(2)在列表尾添加元素

  • 利用.:+在列表尾添加新元素

  • 在列表list1的尾部追加一个元素100,生成一个新列表 list4列表list1没有变的

 

  • 既然0 :: list1是在list1前面添加新元素,我们自然会猜想list1 :: 100是在list1后面添加新元素,验证一下我们的猜想。 

  • 列表后的::运算符要连接一个列表 

3、列表合并操作

  • List也支持合并操作

  • 创建两个列表list1list2

 

  • list1list2合并生成列表list3list1元素在前,list2元素在后

  • list1list2合并生成列表list4list2元素在前,list1元素在后 
  • 用方法调用来实现list1和list2 合并生成 list4
  • 结论:冒号:靠近哪个列表,那个列表就位于合并列表之前

  • 思考题:数组可以用append来追加元素,定长列表可以吗?

4、二维列表

  • 列表的列表称为二维列表,其实就是嵌套的列表
  • 可以利用二维列表来对应MySQL数据表的多条
  • 定义二维列表students, 让scala自动推断stuents常量的类型

val students = List(
    List(1, "李文丽", 19),
    List(2, "肖玉玲", 18),
    List(3, "郑刚林", 20)) 

  • 遍历二维列表students

 for (student <- students) {
    for (field <- student)
        print(field.toString + "\t")
    println()
}

  • 课堂练习:换种方式遍历二维列表
  • 利用scala特殊双重循环和流间变量

  • 利用遍历算子

(二)可变列表

1、创建可变列表

  • 可变List需要使用scala.collection.mutable.ListBuffer
  • 创建列表时初始化数据(静态初始化)

  •  先创建空列表,然后利用+=运算符添加数据

  • 思考题:可用append方法给可变列表添加新元素吗?

  • 两种方法添加元素

2、列表合并

  • 将列表list1与列表list2合并,list1在前,list2在后

  •  将列表list1与列表list2合并,list2在前,list1在后

3、列表排序

  • 列表升序和降序(降序 = 升序 + 反序)

4、列表总和、平均值、最值

  • 计算总和、最值可以直接调用列表方法完成,平均值得自己计算

5、添加新元素

  • 添加新元素有两种方法:在末尾添加新元素用append方法;在中间插入新元素用insert方法

  • 调用可变列表的insert(pos, value),在pos位置插入新元素value

  • 特殊情况,在列表头插入新元素,pos = 0

  • 特殊情况,在列表尾追加新元素,pos = list.length,此时相当于执行append方法的效果

6、移除列表元素

  • 调用可变列表的remove(pos, count)方法,从pos位置开始移除count个列表元素
  • 任务:移除list列表中的第6、7、8个元素

  • 课堂练习
  1. 创建整型可变空列表,添加1、3、5、7四个元素,在5和7之间插入元素6,移除开头的1、3两个元素,统计列表元素总和、最大值和最小值,最后将列表降序输出。
  2. 创建整型列表,包含12、5、8、12、9、7、45、16、78、10、3,分别输出奇数列表和偶数列表。(方法一:采用循环嵌套双分支结构;方法二:采用过滤算子来处理)
  • 方法一

  • 方法二

三、映射 (Map)

  • Scala中的Map也分可变Map和不可变Map,默认为不可变Map。

(一)不可变映射

1、创建不可变映射

  • 创建不可变映射mp,用键->值的形式

  • 创建不可变映射mp,用(键, 值)的形式

  • 注意:Map是特质(Scala里的trait,相当于Java里的Interface),不能实例化 

2、遍历不可变映射

  • 利用for循环来实现遍历

  • 调用mp.keysforeach实现遍历 

  • 能够按键修改映射的值?

(二)可变映射

  • 创建可变Map需要引入类scala.collection.mutable.Map,创建方式与上述不可变Map相同。

1、创建可变映射

  • 创建可变映射mp

2、修改可变映射

  • 将键02的值改为man(键02存在,执行修改操作)

 

  • 将键05的值改为belle(键05存在,执行添加操作) 

3、查询可变映射

  • 查询键02的值,如果没有查到,则返回键02不存在

  • 查询键08的值,如果没有查到,则返回键08不存在 

 

4、添加元素

  • 查看可变映射当前值

  • 用两种方式添加元素 

  • 因为数组和列表都可以用append方法来添加新元素,我们试一试映射可不可以 

  •  总结

5、删除元素

  • 删除存在的键 07 对应的元素

  • 删除不存在的键 11 对应的元素,不报错,映射也没有变化 

  • 试一试能否用remove方法来删除映射的元素

四、元组 (Tuple)

  • 元组是一个可以存放不同类型对象的集合,元组中的元素不可以修改。

(一)定义元组

1、直接赋值定义元组

  • 定义一个元组student

2、创建指定长度的元组

  • 定义指定长度的元组,其中Tuple3是一个元组类,代表元组长度为3

  • 目前,Scala支持的元组最大长度为22,即可以使用Tuple1Tuple22。元组的实际类型取决于元素数量和元素的类型。

(二)访问元组

  • 使用方法_1、_2、_3访问元组的元素,与数组和字符串的位置不同,元组的元素下标从1开始。
  • 访问元组的3个元素

  • 元组不能像数组或列表那样通过圆括号加下标的方式来访问元素

  • 访问元组的第6个元素(不存在的元素),报错 

(三)迭代元组

  • 直接用for循环遍历元素是不行的

  • 使用元组的productIterator()方法产生全部元素构成的迭代器,然后遍历迭代器

  • 使用for循环遍历元组生成迭代器

(四)元组转为字符串

  • 使用Tuple.toString()方法可将元组全部元素组合成一个字符串

  • 注意:元组与字符串进行连接运算,元组会自动转换成字符串

课堂练习:对一个字符串进行词频统计

  • 创建文件 /home/test.txt

方法一

  • 读取磁盘文件,然后输出

  • 将迭代器的全部行转成列表,然后进行拼接,用空格作为分隔符

  • 将字符串按空格进行拆分,得到单词数组

  • 对单词数组进行映射操作,得到一个元组(单词, 1)的数组
  • 按单词分组,其实是按元组的第一个元素来分组
  • 将每个单词的出现次数合并成数组
  • 将每个单词的出现次数数组进行归并运算

  • 输出词频统计结果

方法二

  • 采用了将groupBymapValues方法合并的groupMap方法

方法三

  • 采用groupMapReduce方法更简单

  •  在day03包里创建Example01对象

package day03

import scala.io.Source
/**
 * 功能:词频统计
 * 作者:柠檬
 * 日期:2023年03月23日
 */
object Example01 {
  def main(args: Array[String]): Unit = {
    val iterator = Source.fromFile("test.txt") // 获取迭代器
    val text = iterator.getLines().toList.mkString(" ") // 降维处理
    val words = text.split(" ")  // 拆分处理,化整为零
    val mp = words.map((_, 1))  // 映射,单词计数
    val wc = mp.groupMapReduce(_._1)(_ => 1)(_ + _) // 分组映射归纳
    wc.foreach(println) // 遍历输出
  }
}
  • 在ScalaDome.iml下创建文档test.txt

  • 运行程序,查看结果

五、集合 (Set)

  • Scala Set集合存储的对象不可重复。Set集合分为可变集合和不可变集合,默认情况下,Scala使用的是不可变集合,如果要使用可变集合,就需要引用scala.collection.mutable.Set类。
  • 集合的三大特点:确定性、互异性、无序性
  • 关于Set的API文档:https://www.scala-lang.org/api/current/scala/collection/Set.html

 

(一)定义集合

  • 定义一个空的不可变集合set1(Nothing - 一无所有,Scala所有类的子类)

  • 定义一个非空的不可变集合set2(Any - 包罗万象,Scala所有类的父类)

  • 注意:在创建集合时,4.5是第二个元素,但是创建完之后的集合里,4.5成为了最后一个元素,这正好说明了集合的无序性。

(二)增减元素

  • 与列表一样,对于不可变集合进行元素的增加和删除实际上会产生一个新集合,原来的集合并没有改变

  • 创建一个不可变集合set

  • 添加一个集合不存在的元素 - 100

  • 添加一个集合存在的元素1,集合里始终只有一个1(集合具有互异性) 

 

  •  当然,23两个元素也是加不进去的

 

  • 减去一个存在的元素2 

  • 减去一个不存在的元素666,没有任何动静 

(三)集合方法

  • 创建一个集合cities

1、获取首元素

  • 调用head方法

2、获取去首子集合

  • 调用tail方法,去掉了集合里的第一个元素上海

课堂练习:删除排前的三个城市

3、两个集合求并集

  • 利用++运算符或union方法求两个集合的并集
  • 两个集合都有62,但是并集里只出现1

4、两个集合求交集

  • 利用.&.intersect()方法求两个集合的交集

5、求集合的最值

  • 利用maxmin方法求集合最值

6、求集合的总和和平均值

  • 利用sum方法求和

7、集合的遍历

  • 利用for循环遍历集合

六、课后作业

任务:IP地址去重

  • 在项目根目录创建ips.txt文件

  • 创建Exercise02对象完成去重工作

package day03

import java.io.FileWriter

import scala.io.Source

/**
 * 功能:去重
 * 作者:柠檬
 * 日期:2023年03月23日
 */
object Exercise02 {
  def main(args: Array[String]): Unit = {
    val lines = Source.fromFile("ips.txt").getLines()
    var set = Set[String]()
    for (line <- lines) set = set + line
    println("去重后的IP地址:\n")
    val fw = new FileWriter("distinct_ips.txt")
    for (x <- set) {
      println(x)
      fw.write(x + "/n")
    }
    println("\n去重后的IP地址写入[distinct_ips.txt]~")
    fw.close()
  }

}
  • 运行程序,查看结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值