二维码
微世推网

扫一扫关注

当前位置: 首页 » 快报资讯 » 今日快报 » 正文

scala_系列之_05scala_数据结构

放大字体  缩小字体 发布日期:2021-12-28 04:18:05    作者:郭孜辰    浏览次数:318
导读

6 数据结构 在scala 编程中经常需要用到各种数据结构,比如数组(Array)、元组(Tuple)、列表(List)、映射(Map)、集合(Set)等。​ Scala同时支持可变集合和不可变集合,不可变集合从不可变,可以安全得并发访问;​ 不可变集合:scala.collection.immutable​ 可变集合: scala.collection.mutable​ Scala优先采用

6 数据结构

在scala 编程中经常需要用到各种数据结构,比如数组(Array)、元组(Tuple)、列表(List)、映射(Map)、集合(Set)等。

​ Scala同时支持可变集合和不可变集合,不可变集合从不可变,可以安全得并发访问;

​ 不可变集合:scala.collection.immutable

​ 可变集合: scala.collection.mutable

​ Scala优先采用不可变集合,对于几乎所有得集合类,Scala都同时提供了可变和不可变得版本;

不可变集合层次结构:

可变集合层次结构:

6.1 数组#

​ 数组是一种可变得、可索引得、元素具有相同类型得数据集合;

​ 分为定长和变长得,也就是可以改变长度和固定长度得(同样 集合、映射、元组也分为定长和变长);

​ 定长不用引用第3方得包,变长需要引用;

1)定长数组

// 在Array得object对象中有apply方法(就是创建对象得),不需要new关键字了scala> val arr = Array[Int](1,2,3)arr: Array[Int] = Array(1, 2, 3)// 获取数组长度scala> arr.sizeres32: Int = 3// 获取数组元素, 下标从0开始,用()括起来scala> arr(0)res33: Int = 1// 不可变数组可以修改元素scala> arr(0) = 10scala> println(arr)[I等49825659// 通过toBUffer来看到内部数据scala> println(arr.toBuffer)ArrayBuffer(10, 2, 3)// 数组内部存储得类型是一致得,如果不一致,就找公共得类型scala> val arr = Array(1,"aa",Array[Int](1,2,3))arr: Array[Any] = Array(1, aa, Array(1, 2, 3))scala> arr(2)res37: Any = Array(1, 2, 3)scala> arr(2)(1)<console>:13: error: Any does not take parameters arr(2)(1) ^// Any类型什么也干不了,需要强转成指定类型scala> res37.asInstanceOf[Array[Int]]res39: Array[Int] = Array(1, 2, 3)scala> res39(1)res40: Int = 2scala> val arr = Array[Int](1,4,2,5,6,7)arr: Array[Int] = Array(1, 4, 2, 5, 6, 7)// 升序排序scala> arr.sortedres41: Array[Int] = Array(1, 2, 4, 5, 6, 7)// 降序排序scala> arr.sorted.reverseres42: Array[Int] = Array(7, 6, 5, 4, 2, 1)// 聚合函数scala> arr.sumres43: Int = 25scala> arr.maxres45: Int = 7scala> arr.minres46: Int = 1// 数组元素遍历scala> for(i <- arr) print(s"${i} ")1 4 2 5 6 7scala>// 数组下标方式遍历scala> for(i <- 0 until arr.size) print(s"${arr(i)} ")1 4 2 5 6 7scala> arr.sizeres49: Int = 6scala> arr.lengthres50: Int = 6// 数组和yield产生新数组scala> for(i <- arr) yield i * 10res51: Array[Int] = Array(10, 40, 20, 50, 60, 70)

注意:

​ 设置带初始值得定长数组不能用new,因为是调用Array得静态对象,这个静态对象可以传递多个参数,而new得是调用类得构造方法只能接受一个参数就是数组得长度

2)变长数组

不能直接使用,需要引用ArrayBuffer这个类,不引入就找不到这个类

scala> val arr = new ArrayBuffer[Int]<console>:11: error: not found: type ArrayBuffer val arr = new ArrayBuffer[Int] ^// 变长数组需要手动引入scala> import scala.collection.mutable.ArrayBufferimport scala.collection.mutable.ArrayBufferscala> val arr = new ArrayBuffer[Int]arr: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()// 后面追加scala> arr.append(-1)// 指定下标插入scala> arr.insert(0,-2)scala> println(arr)ArrayBuffer(-2, -1)// + 用来加元素和元组scala> arr += 1res55: arr.type = ArrayBuffer(-2, -1, 1)scala> arr += (2,3)res56: arr.type = ArrayBuffer(-2, -1, 1, 2, 3)// ++ 用来++同类(序列)scala> arr ++= Array[Int](4,5)res57: arr.type = ArrayBuffer(-2, -1, 1, 2, 3, 4, 5)scala> arr ++= ArrayBuffer[Int](6,7)res58: arr.type = ArrayBuffer(-2, -1, 1, 2, 3, 4, 5, 6, 7)// -- 用来--同类(序列)scala> arr --= ArrayBuffer[Int](6,7)res59: arr.type = ArrayBuffer(-2, -1, 1, 2, 3, 4, 5)scala> arr --= Array[Int](4,5)res60: arr.type = ArrayBuffer(-2, -1, 1, 2, 3)// - 用来-元素或元组scala> arr -= (2,3)res61: arr.type = ArrayBuffer(-2, -1, 1)scala> arr -= 1res62: arr.type = ArrayBuffer(-2, -1)// remove 减下标并能获取到下标对应得元素scala> arr.remove(0)res63: Int = -2scala> println(arr)ArrayBuffer(-1)

3)定长数组与变长数组得相互转换

scala> val arr = Array[Int](1,2,3)arr: Array[Int] = Array(1, 2, 3)// Array ---> ArrayBufferscala> arr.toBufferres65: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 2, 3)// ArrayBuffer ---> Arrayscala> res65.toArrayres66: Array[Int] = Array(1, 2, 3)6.2 元组#

​ scala 得元组是对多个不同类型对象得一种简单封装。Scala 提供了TupleN 类(N得范围为1 ~ 22),用于创建一个包含N个元素得元组。

​ 构造元组只需把多个元素用逗号隔开并用圆括号括起来。

​ 元组取值时,元组得下标是从1开始得,而数组得下标是从0开始得,要注意区别;

// 元组得每个元素都可以看到具体得类型scala> val t1 = (1, "hainiu", Array[Int](1,2,3), (4,5))t1: (Int, String, Array[Int], (Int, Int)) = (1,hainiu,Array(1, 2, 3),(4,5))// 元组用 t1._N, N从1开始scala> t1._2res15: String = hainiuscala> t1._3(1)res16: Int = 2scala> t1._4._2res17: Int = 5// 元组元素不可修改scala> t1._1 = 10<console>:12: error: reassignment to val t1._1 = 106.3 列表#

1)不可变列表

不可变列表:元素和长度都不可变

// 不可变列表:元素和长度都不可变scala> val list = List[Int](1,2,3)list: List[Int] = List(1, 2, 3)scala> list(1)res19: Int = 2// 元素不可变scala> list(1) = 10<console>:13: error: value update is not a member of List[Int] list(1) = 10 ^scala> list.sizeres21: Int = 3

但可以产生新得列表

scala> val list2 = List(1,2,3)list2: List[Int] = List(1, 2, 3)// 在list2 前面加 0 ---> List(0, 1, 2, 3)scala> list2.::(0)scala> list2.+:(0)scala> 0 :: list2scala> 0 +: list2// 在list2 后面加 0 ---> List(1, 2, 3, 0)scala> list2.:+(0)scala> list2 :+ 0// 合并两个list并生成新得listscala> list2 ::: List(2,3,4)res29: List[Int] = List(1, 2, 3, 2, 3, 4)scala> list2 ++ List(2,3,4)res30: List[Int] = List(1, 2, 3, 2, 3, 4)// Nil 代表空列表scala> Nilres31: scala.collection.immutable.Nil.type = List()scala> 0 :: 1 :: Nilres32: List[Int] = List(0, 1)

2)可变列表

// 需要主动引入可变列表scala> import scala.collection.mutable.ListBufferimport scala.collection.mutable.ListBufferscala> val list = new ListBuffer[Int]list: scala.collection.mutable.ListBuffer[Int] = ListBuffer()// 添加元素scala> list.append(1)// 在指定位置插入scala> list.insert(0, -1)// + 用来加元素和元组scala> list += 2res15: list.type = ListBuffer(-1, 1, 2)scala> list += (3,4)res16: list.type = ListBuffer(-1, 1, 2, 3, 4)// ++ 用来++同类(序列)scala> list ++= Array(5,6)res17: list.type = ListBuffer(-1, 1, 2, 3, 4, 5, 6)scala> list ++= List(7,8)res18: list.type = ListBuffer(-1, 1, 2, 3, 4, 5, 6, 7, 8)// 删除元素, 减下标元素scala> list.remove(0)res19: Int = -1scala> list.sizeres20: Int = 8// -- 用来--同类(序列)scala> list --= List(7,8)res21: list.type = ListBuffer(1, 2, 3, 4, 5, 6)scala> list --= Array(5,6)res22: list.type = ListBuffer(1, 2, 3, 4)// - 用来减元素和元组scala> list -= (1,2)res23: list.type = ListBuffer(3, 4)scala> list -= 3res24: list.type = ListBuffer(4)

注意:在可变list上也可以调用不可变list得"::","+:",":+","++",":::",区别是可变list返回得是新得ListBuffer,不可变list返回得是新得List

:: 在列表前面添加 【ListBuffer 不可用】

+: 在列表前面添加

:+ 在列表后面添加

++ 两个列表拼接

::: 两个列表拼接 【ListBuffer 不可用】

scala> val list = ListBuffer(1,2,3)list: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)// :: ::: 在可变列表中用不了scala> 0 :: list<console>:14: error: value :: is not a member of scala.collection.mutable.ListBuffer[Int] 0 :: list ^scala> 0 +: listres27: scala.collection.mutable.ListBuffer[Int] = ListBuffer(0, 1, 2, 3)scala> list :+ 0res28: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 0)scala> list ++ List(4,5)res29: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3, 4, 5)scala> list ::: List(4,5)<console>:14: error: type mismatch; found : scala.collection.mutable.ListBuffer[Int] required: List[?] list ::: List(4,5) ^

3)ListBuffer 、 List、ArrayBuffer、Array得转换

6.4 集合#

特性:去重

1)不可变set

scala> val set = Set(1,2,3)set: scala.collection.immutable.Set[Int] = Set(1, 2, 3)scala> set.sizeres36: Int = 3// 获取第壹个元素scala> set.headres37: Int = 1// 获取除了第壹个元素以外得其他元素组成得setscala> set.tailres38: scala.collection.immutable.Set[Int] = Set(2, 3)// 判断集合是否为空scala> set.isEmptyres40: Boolean = false// 使用不可变得HashSet,需要引入不可变HashSetscala> val set = HashSet(1,2,3)<console>:12: error: not found: value HashSet val set = HashSet(1,2,3) ^scala> import scala.collection.immutable.HashSetimport scala.collection.immutable.HashSetscala> val set = HashSet(1,2,3)set: scala.collection.immutable.HashSet[Int] = Set(1, 2, 3)scala> set.sizeres41: Int = 3// 不可变set可以产生新得set集合scala> set + 1res42: scala.collection.immutable.HashSet[Int] = Set(1, 2, 3)scala> set + 4res43: scala.collection.immutable.HashSet[Int] = Set(1, 2, 3, 4)scala> set ++ Set(3,5)res44: scala.collection.immutable.HashSet[Int] = Set(5, 1, 2, 3)

2)可变set

// 引入不可变HashSetscala> import scala.collection.immutable.HashSetimport scala.collection.immutable.HashSetscala> val set = HashSet(1,2,3)set: scala.collection.immutable.HashSet[Int] = Set(1, 2, 3)// 引入可变HashSetscala> import scala.collection.mutable.HashSetimport scala.collection.mutable.HashSet// 报错原因是当前有两个HashSet, 创建对象不知道用哪个scala> val set = new HashSet[Int]<console>:14: error: reference to HashSet is ambiguous;it is imported twice in the same scope byimport scala.collection.mutable.HashSetand import scala.collection.immutable.HashSet val set = new HashSet[Int] ^// 冲突了,起别名,用别名来创建对象scala> import scala.collection.mutable.{HashSet => HashSetMu}import scala.collection.mutable.{HashSet=>HashSetMu}scala> val set = new HashSetMu[Int]set: scala.collection.mutable.HashSet[Int] = Set()// 可变集合得添加scala> set.add(1)res45: Boolean = truescala> set.add(1)res46: Boolean = falsescala> set += 2res47: set.type = Set(1, 2)scala> set += (3,4)res48: set.type = Set(1, 2, 3, 4)scala> set ++= Set(4,5)res49: set.type = Set(1, 5, 2, 3, 4)scala> println(set)Set(1, 5, 2, 3, 4)// 因为set不按照下标取遍历, remove减得是元素scala> set.remove(5)res51: Boolean = truescala> set -= 1res52: set.type = Set(2, 3, 4)scala> set -= (2,3)res53: set.type = Set(4)scala> set --= Set(4)res54: set.type = Set()scala> set.isEmptyres55: Boolean = true6.5映射#

映射也就是一个hash表,相当于java里得map

1)不可变map

// 创建不可变map对象// kv键值对:可以用 k -> v 表示, 也可以用 (k, v) 表示scala> val map = Map("a"->1, "b"->(1,2), ("c",3))map: scala.collection.immutable.Map[String,Any] = Map(a -> 1, b -> (1,2), c -> 3)scala> map.sizeres0: Int = 3// 获取key对应得value scala> map("a")res1: Any = 1// 强转scala> res0.asInstanceOf[Int]res2: Int = 1// 不可变map不能修改元素 scala> map("a") = 10<console>:13: error: value update is not a member of scala.collection.immutable.Map[String,Any] map("a") = 10 ^// 获取时如果key不存在,抛异常scala> map("d")java.util.NoSuchElementException: key not found: d at scala.collection.MapLike$class.default(MapLike.scala:228) at scala.collection.AbstractMap.default(Map.scala:59) at scala.collection.MapLike$class.apply(MapLike.scala:141) at scala.collection.AbstractMap.apply(Map.scala:59) ... 32 elided// 解决方案1: 通过get方法,获取Option对象// Option 对象有两个子类:// None:代表没数据// Some: 代表有数据, 可通过get() 提取Some对象里得数据scala> map.get("d")res5: Option[Any] = None// 获取对应得Option对象scala> map.get("a")res6: Option[Any] = Some(1)// 提取数据scala> res6.getres7: Any = 1// 解决方案2:通过getOrElse方法,如果key不存在,将设置得默认值返回scala> map.getOrElse("d", "default value")res8: Any = default value

不可变 Map 内部元素不可变,但可以产生新得Map

scala> val map = Map("a"->1)map: scala.collection.immutable.Map[String,Int] = Map(a -> 1)scala> map + ("b"-> 2)res9: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)scala> map + (("c", 3))res10: scala.collection.immutable.Map[String,Int] = Map(a -> 1, c -> 3)scala> map ++ Map("d"-> 4)res11: scala.collection.immutable.Map[String,Int] = Map(a -> 1, d -> 4)scala> res9 - "b"res12: scala.collection.immutable.Map[String,Int] = Map(a -> 1)scala> res11 - ("d")res13: scala.collection.immutable.Map[String,Int] = Map(a -> 1)

2)可变map

添加删除数据

// 引入可变得HashMapscala> import scala.collection.mutable.HashMapimport scala.collection.mutable.HashMapscala> val map = new HashMap[String,Int]map: scala.collection.mutable.HashMap[String,Int] = Map()// 添加数据scala> map.put("a",1)res69: Option[Int] = Nonescala> println(map)Map(a -> 1)scala> map += ("b"-> 2)res71: map.type = Map(b -> 2, a -> 1)scala> map += (("c", 3))res72: map.type = Map(b -> 2, a -> 1, c -> 3)scala> map ++= Map("d"-> 4)res73: map.type = Map(b -> 2, d -> 4, a -> 1, c -> 3)// 删除数据scala> map.remove("a")res74: Option[Int] = Some(1)scala> res74.getres75: Int = 1scala> map -= "b"res76: map.type = Map(d -> 4, c -> 3)scala> map -= ("c","d")res77: map.type = Map()scala> map.isEmptyres79: Boolean = true

遍历map

// 遍历mapscala> val map = HashMap("b" -> 2, "d" -> 4, "a" -> 1, "c" -> 3)map: scala.collection.mutable.HashMap[String,Int] = Map(b -> 2, d -> 4, a -> 1, c -> 3)// 以keyset得方式根据key找valuescala> for(k <- map.keySet)println(s"k:${k}, v:${map(k)}")k:b, v:2k:d, v:4k:a, v:1k:c, v:3// 直接遍历一组k,vscala> for((k,v) <- map)println(s"k:${k}, v:${v}")k:b, v:2k:d, v:4k:a, v:1k:c, v:3// 遍历valuescala> for(v <- map.values)println(s"v:${v}")v:2v:4v:1v:3

利用元组进行组合赋值

val re,(a,b,c,d,e,f,g) = ("a",1,1L,1.0,Array(1,2),Map(("a",1)),"b" -> 2)

toMap操作——将对偶得数组转换成map

// 对偶数组scala> val arr1 = Array(("a",1), ("b",2))arr1: Array[(String, Int)] = Array((a,1), (b,2))scala> arr1.toMapres86: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)// 对偶列表scala> val list = List(("a",1), ("b",2))list: List[(String, Int)] = List((a,1), (b,2))scala> list.toMapres87: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)

zip操作(拉链操作),通过拉链操作得到对偶数组或列表

scala> val arr1 = Array("a", "b", "c")arr1: Array[String] = Array(a, b, c)scala> val arr2 = Array(1,2)arr2: Array[Int] = Array(1, 2)// 通过拉链得到对偶数组,如果对不齐就舍去scala> arr1.zip(arr2)res88: Array[(String, Int)] = Array((a,1), (b,2))scala> arr2.zip(arr1)res89: Array[(Int, String)] = Array((1,a), (2,b))scala> arr1 zip arr2res90: Array[(String, Int)] = Array((a,1), (b,2))scala> res88.toMapres91: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)

如何将 List(Array("a",1), Array("b",2)) 转化成 Map("a"->1, "b"-> 2)

海汼部落,原文链接:(hainiubl/topics/75676)

 
(文/郭孜辰)
免责声明
• 
本文仅代表发布者:郭孜辰个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,需自行承担相应责任。涉及到版权或其他问题,请及时联系我们删除处理邮件:weilaitui@qq.com。
 

Copyright©2015-2025 粤公网安备 44030702000869号

粤ICP备16078936号

微信

关注
微信

微信二维码

WAP二维码

客服

联系
客服

联系客服:

24在线QQ: 770665880

客服电话: 020-82301567

E_mail邮箱: weilaitui@qq.com

微信公众号: weishitui

韩瑞 小英 张泽

工作时间:

周一至周五: 08:00 - 24:00

反馈

用户
反馈