scala 集合总结(Seq、Map、Set、List、Tuple、Option)

https://docs.scala-lang.org/scala3/book/collections-classes.html
https://docs.scala-lang.org/overviews/collections-2.13/overview.html

scala 集合的三大类型

从较高的层次来看 Scala 集合,主要有以下三个类别可供选择:

  • Sequences是元素的顺序集合,可以是索引的(如数组)或线性的(如链表)
  • Maps包含键/值对的集合,类似于Java的Map、Python的dict
  • Sets是唯一元素的无序集合

所有这些都是基本类型,并且具有用于特定目的的子类型,例如并发、缓存和流式处理。除了这三个主要类别之外,还有其他有用的集合类型,包括ranges, stacks, queues。

下图显示了scala.collection包中的集合类型。这些都是高级抽象类或特征,通常具有不可变和可变的实现。

在这里插入图片描述

scala.collection.immutable(不可变集合)

scala.collection.immutable包中的集合保证对每个人都是不可变的。这样的集合在创建后就永远不会改变。因此,您可以相信在不同时间点重复访问相同集合值将始终产生具有相同元素的集合这一事实。

下图显示包scala.collection.immutable中的所有集合:

在这里插入图片描述

scala.collection.mutable(可变集合)

scala.collection.mutable包中的集合具有一些更改集合的操作。因此,处理可变集合意味着您需要了解哪些代码在何时更改了哪个集合。

下图显示包scala.collection.mutable中的所有集合:

在这里插入图片描述

默认情况下,Scala 总是选择不可变集合。例如,如果只是编写Set而没有任何前缀或没有 Set从某处导入,将获得一个不可变集,如果编写 Iterable将获得一个不可变的可迭代集合,因为这些是从scala包中导入的默认绑定。

常用集合总结

集合类型不变的可变的描述
List线性(链表)、不可变序列。List[T] 是类型 T 的链表。
Vector一个索引的、不可变的序列。
LazyList惰性不可变链表,其元素仅在需要时才计算;适用于大型或无限序列。
ArrayBuffer可变索引序列的首选类型。
ListBuffer当你想要一个可变的List;通常转换为List
Map由成对的键和值组成的可迭代集合。可通过键检索值。
Set没有重复元素的可迭代集合。Set中元素类型相同。

如上所示,MapSet有不可变和可变版本。

ListVectorLazyListArrayBufferListBuffer均是Seq的子类。

其他集合:

https://www.tutorialspoint.com/scala_collections/scala_collections_overview.htm

集合类型描述
Tuple与数组或列表不同,元组可以包含不同类型的对象,适合存放异构类型元素。
OptionOption[T] 为给定类型的零个或一个元素提供容器。

Iterator:迭代器不是集合,而是一种逐个访问集合元素的方式。

使用时应该选择哪个Seq子类

选择序列(顺序集合元素)时,您有两个主要决定:

  • 序列应该被索引(如数组),允许快速访问任何元素,还是应该作为线性链表实现?
  • 你想要一个可变的还是不可变的集合?

此处显示了针对可变/不可变和索引/线性组合的推荐的通用“转到”顺序集合:

类型/类别不变的可变的
索引VectorArrayBuffer
线性(链表)ListListBuffer

例如,如果您需要一个不可变的索引集合,通常您应该使用Vector。相反,如果您需要一个可变的索引集合,请使用ArrayBuffer

Vector 与 List 的比较

https://stackoverflow.com/a/35115252/17434375

  • List 是一个单链表,仅提供线性迭代和恒定时间前置,头/尾分解。
  • Vector 是一个 base-32 整数 trie,即它是一种节点度数为 32 的搜索树。使用这种结构,Vector 可以相当快地 O(log_32(n)) 提供大多数常见操作。这适用于头/尾中的前置、追加、更新、随机访问、分解(prepend, append, update, random access, decomposition in head/tail)。按顺序迭代是线性时间。

这看起来好像在几乎所有情况下 Vector 都是 List 的一个很好的替代品,但是前置、分解和迭代通常是函数式程序中对序列的关键操作,并且这些操作的常量对于 vector 来说高得多,由于其更复杂的结构。

对于顺序操作,List 可能要快一点;对于大量的随机访问和不同的更新,应该使用 Vector。

Seq 与 List 的关系

Seq是具有定义的元素顺序的 Iterable 。提供了一种apply()索引方法,范围从 0 到Seq长度。

List是作为不可变链表实现的 Seq 。它最适用于具有后进先出 (LIFO) 访问模式的情况。

https://stackoverflow.com/a/44787827/17434375

Seq is a trait that List implements.

我的理解是:Seq是上层接口抽象,List是下层实现(不可变链表)。这样设计有个好处,就是定义函数时参数类型设为Seq,在调用的时候传入参数可以是Seq子类(比如 List 或者 Vector 等)。Vector的好处是能更快随机访问,以及更适合并行算法。

如果定义Seq时未指定容器类型,则底层数据结构默认为List

scala> val a = Seq(1,2,3) // 不指明a的数据类型就默认是List
a: Seq[Int] = List(1, 2, 3)
// 等价于
scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)
Seq 与 Array 的关系

https://www.baeldung.com/scala/array-vs-wrappedarray

Scala程序最终被编译为.class文件运行在JVM虚拟机中,所以它是JVM下的语言一种,在实际的大数据开发任务当中,Java和Scala都运行于JVM之上,也能更好地集成。

Scala Array对应于Java中的Array。

scala写法

val simpleArray: Array[Int] = Array(1, 2, 3, 4, 5)

java写法

int[] simpleArray = new int[]{1, 2, 3, 4, 5};

这两种代码编译生成的字节码相同,在字节码级别使用原始类型。Scala Array[Int]在底层被转换为 Java int[]数组。这同样适用于Double、Float、Long和其他“盒装”类型。

Scala 提供了比 Java 更多的Array类功能:

  • 数组是通用的,所以我们可以创建一个Array[T],其中 T 可以是抽象类型或具体类型。
  • 数组是Seq兼容的。我们可以在需要 Seq[T] 的地方传递 Array[T]。
  • 数组支持所有序列操作。

因此,即使 Scala Array映射到原生 Java 数组,我们也可以将 Array 用作 Seq。

在scala 2.13版本,这是通过将Array隐式转换为ArraySeq(ArraySeq是Seq的子类)来完成的。

Scala 调用wrapIntArray()方法将Array转换为ArraySeq实例。

注意不同scala版本的隐式转换不一样:

// Scala 2.13+
scala> val a:Seq[Int] = Array(1,2,3)
// warning: method copyArrayToImmutableIndexedSeq in class LowPriorityImplicits2 is deprecated (since 2.13.0): Implicit conversions from Array to immutable.IndexedSeq are implemented by copying; Use the more efficient non-copying ArraySeq.unsafeWrapArray or an explicit toIndexedSeq call
a: Seq[Int] = ArraySeq(1, 2, 3)
// Scala 2.12
scala> val a:Seq[Int] = Array(1,2,3)
a: Seq[Int] = WrappedArray(1, 2, 3)
// 等价于
scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)
scala> a.toSeq
res: Seq[Int] = WrappedArray(1, 2, 3)
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nefu-ljw

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

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

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

打赏作者

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

抵扣说明:

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

余额充值