scala中的数据结构

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
简介: 对于Scala来说,同时支持可变集合和不可变集合,不可变集合一直都不会发生变化,可以安全的并发访问。Scala优先采用不可变集合,同时几乎所有的集合类,Scala都同时提供了可变和不可变的版本。下面是两个主要的包:不可变集合:scala.collection.immutable、可变集合: scala.collection.mutable。

注意:下面的例子均在scala shell中演示的

一、数据结构介绍

对于Scala来说,同时支持可变集合和不可变集合,不可变集合一直都不会发生变化,可以安全的并发访问。
Scala优先采用不可变集合,同时几乎所有的集合类,Scala都同时提供了可变和不可变的版本。
下面是两个主要的包:不可变集合:scala.collection.immutable、可变集合: scala.collection.mutable。

不可变集合继承层次:
在这里插入图片描述
可变集合继承层次:
在这里插入图片描述

二、实操

1、数组

可以用数组来存放一组数据。scala中,有两种数组,一种是定长数组,另一种是变长数组。

1.1、定长数组

定长数组指的是数组的长度是不允许改变的,数组的元素是可以改变的。

// 通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)

// 用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3...)

数组的泛型使用[]来指定,使用()来获取元素

scala> val a=new Array[Int](5)
a: Array[Int] = Array(0, 0, 0, 0, 0)

scala> a(0)
res0: Int = 0

scala> a(0)=3

scala> a
res2: Array[Int] = Array(3, 0, 0, 0, 0)

scala> val b = Array("hadoop","spark","flink")
b: Array[String] = Array(hadoop, spark, flink)

scala> b(0)
res3: String = hadoop

scala> b.length
res4: Int = 3
1.2、变长数组

变长数组指的是数组的长度是可变的,可以往数组中添加、删除元素。创建变长数组,需要提前导入ArrayBuffer类。

import scala.collection.mutable.ArrayBuffer

创建空的ArrayBuffer变长数组

val/var a = ArrayBuffer[元素类型]()

创建带有初始元素的ArrayBuffer

val/var a = ArrayBuffer(元素1,元素2,元素3....)

示例:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C9MbI5kx-1653812332984)(en-resource://database/28654:1)]

scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

//定义一个长度为0的整型变长数组
scala> val a=ArrayBuffer[Int]()
a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

//定义一个有初始元素的变长数组
scala> val b = ArrayBuffer("hadoop", "flink", "spark")
b: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, flink, spark)

变长数组的增删改操作

  • 使用+=添加元素
  • 使用-=删除元素
  • 使用++=追加一个数组到变长数组

示例:

// 定义变长数组
scala> val a = ArrayBuffer("hadoop", "spark", "flink")
a: scala.collection.mutable.ArrayBuffer[String] = ArrayBuffer(hadoop, spark, flink)

// 追加一个元素
scala> a += "hive"
res5: a.type = ArrayBuffer(hadoop, spark, flink, hive)

// 删除一个元素
scala> a -= "spark"
res7: a.type = ArrayBuffer(hadoop, flink, hive)

//可以连着使用
scala> a += "clickhouse" -= "hadoop"
res8: a.type = ArrayBuffer(flink, hive, clickhouse)

// 追加一个数组
scala> a ++= Array("canal", "flume")
res9: a.type = ArrayBuffer(flink, hive, clickhouse, canal, flume)

//任意位置插入、删除元素,这种方法效率不高
//在index 1之前插入元素
a.insert(1, "hbase")    

//插入多个
a.insert(1, "elasticsearch", "hudi")

//移除一个
a.remove(1)

//移除多个,第二个参数:移除的元素个数
//从第二个元素开始,移除2个元素
a.remove(2, 2)

//移除最后2个元素, 高效
a.trimEnd(2)

//输出查看
println(a.toString)

技巧:如果要定义一个Array,但元素个数不确定,可以先将元素写入一个ArrayBuffer,然后再将ArrayBuffer转换成Array

scala> val arr2 = ArrayBuffer(1, 2, 3)
arr2: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

scala> arr2.toArray
res18: Array[Int] = Array(1, 2, 3)

同时可以将Array转换成ArrayBuffer

scala> val arr = Array(1, 2, 3)
arr: Array[Int] = Array(1, 2, 3)

scala> arr.toBuffer
res16: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)

同时scala集合也可以与java集合互转。

1.3、遍历数组

可以使用以下两种方式来遍历数组:

  • 直接遍历数组中的元素(类比java foreach)
  • 索引遍历数组中的元素(类比java for i)

示例:

scala> for(i <- a) println(i)
flink
hudi
clickhouse

//to
scala> for(i <- 0 to a.length -1) println(a(i))
flink
hudi
clickhouse

//until
scala> for(i <- 0 until a.length) println(a(i))
flink
hudi
clickhouse


//0 until n 生成一系列的数字,包含0,不包含n
//0 to n 包含0,也包含n

//util用法
scala> for(i <- 0 until (a.length, 2)) println(a(i))
flink
clickhouse
1.4、数组常用操作

数组常用的计算操作。sum、max、min、sorted方法。

示例:

scala> val array=Array(1,5,4,2,6)
array: Array[Int] = Array(1, 5, 4, 2, 6)

//求和
scala> array.sum
res27: Int = 18

//求最大值
scala> array.max
res28: Int = 6

//求最小值
scala> array.min
res29: Int = 1

//生成新的数组,升序,array保持不变
scala> array.sorted
res30: Array[Int] = Array(1, 2, 4, 5, 6)

//降序  reverse 反转
scala> array.sorted.reverse
res31: Array[Int] = Array(6, 5, 4, 2, 1)

// 字符串排序是通过按照字典序排序的
scala> val array01=Array("Apache", "Spark", "Flink", "Kafka")
array01: Array[String] = Array(Apache, Spark, Flink, Kafka)

scala> array01.min
res32: String = Apache

scala> array01.max
res33: String = Spark
2、元组

元组可以用来包含一组不同类型的值。例如:姓名,年龄,性别,出生年月。元组的元素是不可变的。

使用括号来定义元组

val/var 元组变量名称 = (元素1, 元素2, 元素3....)

使用箭头来定义元素(元组只有两个元素)

val/var 元组 = 元素1->元素2

示例:

// 直接使用括号来定义一个元组 
scala> val a = (1, "张三", 18, "杭州市")
a: (Int, String, Int, String) = (1,张三,18,杭州市)

//使用箭头来定义元素
scala> val b = 1->2
b: (Int, Int) = (1,2)

访问元组,_1表示访问第一个元素,依次类推
示例

scala> a._2
res34: String = 张三

不能修改元组中的值

scala> a._4="西湖"
<console>:12: error: reassignment to val
       a._4="西湖"
3、映射Map

Map可以称之为映射。它是是key,value对形式的。Map也分为不可变Map和可变Map。

3.1、不可变Map

值不可改变,否则报错

val/var map = Map(键->值, 键->值, 键->值...)    
// 推荐,可读性更好 
val/var map = Map((键, 值), (键, 值), (键, 值), (键, 值)...)

示例:

scala> val map1 = Map("zhangsan"->18, "lisi"->35)
map1: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 18, lisi -> 35)

scala> val map2 = Map(("zhangsan", 18), ("lisi", 35))
map2: scala.collection.immutable.Map[String,Int] = Map(zhangsan -> 18, lisi -> 35)

// 根据key获取value 
scala> map1("zhangsan")
res0: Int = 18

//报错
scala> map1("zhangsan") = 20
<console>:13: error: value update is not a member of scala.collection.immutable.Map[String,Int]
       map1("zhangsan") = 20
3.2、可变Map

可变Map需要手动导入

import scala.collection.mutable.Map

定义语法与不可变Map一致。

示例:

//定义可变的map
scala> val map3 = Map("zhangsan"->18, "lisi"->35)
map3: scala.collection.mutable.Map[String,Int] = Map(lisi -> 35, zhangsan -> 18)

//获取zhangsan这个key对应的value
scala> map3("zhangsan")
res2: Int = 18

//给zhangsan这个key重新赋值value
scala> map3("zhangsan")=50

//查看
scala> map3
res4: scala.collection.mutable.Map[String,Int] = Map(lisi -> 35, zhangsan -> 50)
3.3、Map基本操作

创建一个可变的map

scala> val map = Map("zhangsan"->18, "lisi"->35)
map: scala.collection.mutable.Map[String,Int] = Map(lisi -> 35, zhangsan -> 18)

按照key获取value

// 获取zhagnsan的年龄 
scala> map("zhangsan")
res5: Int = 18

//不存在,报错
map("wangwu") 

// 获取wangwu的年龄,如果wangwu不存在,则返回-1 比较友好,避免遇到不存在的key而报错
scala> map.getOrElse("wangwu", -1)
res7: Int = -1

修改key对应的value

scala> map("lisi")=60

添加key-value键值对

scala> map += ("wangwu" ->35)
res9: map.type = Map(lisi -> 60, zhangsan -> 18, wangwu -> 35)

//添加、更新多个键值对
map += ("wangwu" ->25, "zhaoliu" -> 10)

//等价
map("wangwu") = 35

获取所有的key和所有的value

//获取所有的key的迭代器
scala> map.keys
res13: Iterable[String] = Set(lisi, zhangsan, zhaoliu, wangwu)

//获取所有的key,获得一个集合
scala> map.keySet
res14: scala.collection.Set[String] = Set(lisi, zhangsan, zhaoliu, wangwu)

//获取所有的value
scala> map.values
res15: Iterable[Int] = HashMap(10, 18, 10, 35)

遍历map

//第一种遍历
scala> for(k <- map.keys) println(k+" -> " +map(k))
lisi -> 10
zhangsan -> 18
zhaoliu -> 10
wangwu -> 35


//第二种遍历
scala> for((k,v) <- map) println(k+" -> "+v)
lisi -> 10
zhangsan -> 18
zhaoliu -> 10
wangwu -> 35
4、Set集合

Set是代表没有重复元素的集合。Set具备以下性质:

  • 元素不重复
  • 不保证插入顺序

scala中的set集合也分为两种,一种是不可变集合,另一种是可变集合。

4.1、不可变Set集合

创建语法如下:

//创建一个空的不可变集
val/var 变量名 = Set[类型]()

//给定元素来创建一个不可变集
val/var 变量名 = Set[类型](元素1, 元素2, 元素3...)

示例:

// 创建set集合 
scala> val a = Set(1,1,2,3,4,5)
a: scala.collection.immutable.Set[Int] = Set(5, 1, 2, 3, 4)

// 获取集合的大小 
scala> a.size 
res0: Int = 5

// 遍历集合
scala> for(i <- a) println(i)
5
1
2
3
4


//添加元素生成新的集合
scala> a + 6
res20: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 3, 4)

// 删除一个元素 
scala> a - 1
res21: scala.collection.immutable.Set[Int] = Set(5, 2, 3, 4)

// 删除set集合中存在的元素 
scala> a -- Set(2,3)
res22: scala.collection.immutable.Set[Int] = Set(5, 1, 4)

// 拼接两个集合 
scala> a ++ Set(6,7,8)
res24: scala.collection.immutable.Set[Int] = Set(5, 1, 6, 2, 7, 3, 8, 4)

//求2个Set集合的交集
scala> a & Set(3,4,5,6)
res25: scala.collection.immutable.Set[Int] = Set(5, 3, 4)

注意:这里对不可变的set集合进行添加删除等操作,对于该集合来说是没有发生任何变化,这里是生成了新的集合,新的集合相比于原来的集合来说发生了变化。

4.2、可变Set集合

要使用可变集,必须要手动导入:

import scala.collection.mutable.Set

示例:

//定义可变的set集合
scala> val set=Set(1,2,3,4,5)
set: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4)

//添加单个元素
scala> set +=6 或者 set = set + 6
res10: set.type = Set(1, 5, 2, 6, 3, 4)

//添加多个元素
scala> set +=(6,7,8,9)
res11: set.type = Set(9, 1, 5, 2, 6, 3, 7, 4, 8)

//添加一个set集合中的元素
scala> set ++=Set(10,11)
res12: set.type = Set(9, 1, 5, 2, 6, 3, 10, 7, 4, 11, 8)

//删除一个元素
scala> set -=11
res13: set.type = Set(9, 1, 5, 2, 6, 3, 10, 7, 4, 8)

//删除多个元素
scala> set -=(9,10)
res15: set.type = Set(1, 5, 2, 6, 3, 7, 4, 8)

//删除一个set子集
scala> set --=Set(7,8)
res19: set.type = Set(1,5, 2, 6, 3, 4)

scala> set.remove(1)
res17: Boolean = true

//输出最后的结果
scala> set
res18: scala.collection.mutable.Set[Int] = Set(5, 2, 6, 3, 4)

注意:可变set修改是对原set进行修改的

5、列表 List

List具备以下性质:

  • 可以保存重复的值
  • 有先后顺序

scala中也有两种列表,一种是不可变列表、另一种是可变列表。

5.1、不可变列表

不可变列表就是列表的元素、长度都是不可变的。语法使用 List(元素1, 元素2, 元素3, ...) 来创建一个不可变列表。

val/var 变量名 = List(元素1, 元素2, 元素3...)

//使用 Nil 创建一个不可变的空列表
val/var 变量名 = Nil

//使用 :: 方法创建一个不可变列表
val/var 变量名 = 元素1 :: 元素2 :: Nil

示例:

//创建一个不可变列表,存放(1,2,3,4)
scala> val list1=List(1,2,3,4)
list1: List[Int] = List(1, 2, 3, 4)

//使用Nil创建一个不可变的空列表
scala> val list2=Nil
list2: scala.collection.immutable.Nil.type = List()

//使用 :: 方法创建列表
scala> val list3=1::2::3::Nil
list3: List[Int] = List(1, 2, 3)
5.2、可变列表

可变列表就是列表的元素、长度都是可变的。要使用可变列表,先要导入

import scala.collection.mutable.ListBuffer

使用ListBuffer元素类型创建空的可变列表

val/var 变量名 = ListBuffer[Int]()

使用ListBuffer(元素1, 元素2, 元素3...)创建可变列表

val/var 变量名 = ListBuffer(元素1,元素2,元素3...)

示例:

//定义一个空的可变列表
scala> val a=ListBuffer[Int]()
a: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

//定义一个有初始元素的可变列表
scala> val b=ListBuffer(1,2,3,4)
b: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4)
5.3、列表操作
//定义一个可变的列表
scala> val list=ListBuffer(1,2,3,4)
list: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4)

//获取第一个元素
scala> list(0)
res4: Int = 1
//获取第一个元素
scala> list.head
res5: Int = 1

//获取除了第一个元素外其他元素组成的列表
scala> list.tail
res6: scala.collection.mutable.ListBuffer[Int] = ListBuffer(2, 3, 4)

//添加单个元素
scala> list +=5
res7: list.type = ListBuffer(1, 2, 3, 4, 5)

//添加一个不可变的列表
scala> list ++= List(6,7)
res8: list.type = ListBuffer(1, 2, 3, 4, 5, 6, 7)

//添加一个可变的列表
scala> list ++= ListBuffer(8,9)
res9: list.type = ListBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9)

//删除单个元素
scala> list -= 9
res10: list.type = ListBuffer(1, 2, 3, 4, 5, 6, 7, 8)

//删除一个不可变的列表存在的元素
scala> list --= List(7,8)
res11: list.type = ListBuffer(1, 2, 3, 4, 5, 6)

//删除一个可变的列表存在的元素
scala> list --= ListBuffer(5,6)
res12: list.type = ListBuffer(1, 2, 3, 4)

//可变的列表转为不可变列表
scala> list.toList
res13: List[Int] = List(1, 2, 3, 4)

//可变的列表转为不可变数组
scala> list.toArray
res14: Array[Int] = Array(1, 2, 3, 4)
目录
相关文章
|
6月前
|
安全 Java Scala
Scala集合【上】
Scala集合【上】
|
Scala
162 Scala 集合
162 Scala 集合
43 0
|
6月前
|
存储 Scala 索引
scala中常见数据结构的用法
scala中常见数据结构的用法
44 1
|
6月前
|
存储 前端开发 Java
【Java】集合与数据结构
【Java】JavaSE集合
113 0
|
存储 安全 算法
Java 编程问题:五、数组、集合和数据结构5
Java 编程问题:五、数组、集合和数据结构
73 0
|
安全 Java Shell
Scala 集合基本介绍 | 学习笔记
快速学习 Scala 集合基本介绍
|
缓存 负载均衡 并行计算
SCALA程序设计 第四章:数据结构
SCALA程序设计 数据结构
121 0
|
存储 机器学习/深度学习 人工智能
Java进阶:【集合】认识集合相关的数据结构
Java进阶:【集合】认识集合相关的数据结构
Java进阶:【集合】认识集合相关的数据结构