Scala学习之SCALA 集合类

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala学习之SCALA 集合类相关的知识,希望对你有一定的参考价值。

SCALA COLLECTIONS

原文地址 https://docs.scala-lang.org/overviews/scala-book/collections-101.html

如果您是从 Java 来到 Scala,那么您能做的最好的事情就是忘记 Java 集合类,并按照预期使用 Scala 集合类。 正如本书的一位作者所说,“根据个人经验,当我第一次开始使用 Scala 时,我试图在我的 Scala 代码中使用 Java 集合类,但这一切都减慢了我的进度。”

The main Scala collections classes

您将定期使用的主要 Scala 集合类是:

ClassDescription
ArrayBuffer一个索引的、可变的序列
List线性(链表),不可变序列
Vector一个索引的、不可变的序列
Map基础Map(键/值对)类
Set基础Set

MapSet 有可变和不可变版本。

我们将在以下课程中演示这些课程的基础知识。

在以下有关 Scala 集合类的课程中,无论何时我们使用不可变这个词,都可以安全地假设该类旨在用于函数式编程 (FP) 风格。 使用这些类,您无需修改集合; 您将函数方法应用于集合以创建新结果。 您将在以下示例中看到这意味着什么。

THE ARRAYBUFFER CLASS

https://docs.scala-lang.org/overviews/scala-book/arraybuffer-examples.html

如果您是一名从 Java 来到 Scala 的 OOP 开发人员,那么 ArrayBuffer 类可能最适合您,因此我们将首先演示它。 它是一个可变序列,所以你可以使用它的方法来修改它的内容,这些方法类似于 Java 序列上的方法。

要使用 ArrayBuffer,您必须首先导入它:

import scala.collection.mutable.ArrayBuffer

将其导入本地作用域后,您可以像这样创建一个空的 ArrayBuffer:

val ints = ArrayBuffer[Int]()
val names = ArrayBuffer[String]()

拥有 ArrayBuffer 后,您可以通过多种方式向其中添加元素:

val ints = ArrayBuffer[Int]()
ints += 1
ints += 2

The REPL shows how += works:

scala> ints += 1
res0: ints.type = ArrayBuffer(1)

scala> ints += 2
res1: ints.type = ArrayBuffer(1, 2)

这只是创建 ArrayBuffer 并向其添加元素的一种方法。 您还可以创建一个带有初始元素的 ArrayBuffer,如下所示:

val nums = ArrayBuffer(1, 2, 3)

您可以通过以下几种方法向此 ArrayBuffer 添加更多元素:

val nums = ArrayBuffer(1, 2, 3)

您可以通过以下几种方法向此 ArrayBuffer 添加更多元素:

// add one element
nums += 4

// add multiple elements
nums += 5 += 6

// add multiple elements from another collection
nums ++= List(7, 8, 9)

您可以使用 -=--= 方法从 ArrayBuffer 中删除元素:

// remove one element
nums -= 9

// remove multiple elements
nums -= 7 -= 8

// remove multiple elements using another collection
nums --= Array(5, 6)

下是所有这些示例在 REPL 中的样子:

scala> import scala.collection.mutable.ArrayBuffer

scala> val nums = ArrayBuffer(1, 2, 3)
val nums: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

scala> nums += 4
val res0: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

scala> nums += 5 += 6
val res1: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)

scala> nums ++= List(7, 8, 9)
val res2: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> nums -= 9
val res3: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)

scala> nums -= 7 -= 8
val res4: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6)

scala> nums --= Array(5, 6)
val res5: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

More ways to work with ArrayBuffer

为简要概述,以下是您可以与 ArrayBuffer 一起使用的几种方法:

val a = ArrayBuffer(1, 2, 3)         // ArrayBuffer(1, 2, 3)
a.append(4)                          // ArrayBuffer(1, 2, 3, 4)
a.append(5, 6)                       // ArrayBuffer(1, 2, 3, 4, 5, 6)
a.appendAll(Seq(7,8))                // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8)
a.clear                              // ArrayBuffer()

val a = ArrayBuffer(9, 10)           // ArrayBuffer(9, 10)
a.insert(0, 8)                       // ArrayBuffer(8, 9, 10)
a.insertAll(0, Vector(4, 5, 6, 7))   // ArrayBuffer(4, 5, 6, 7, 8, 9, 10)
a.prepend(3)                         // ArrayBuffer(3, 4, 5, 6, 7, 8, 9, 10)
a.prepend(1, 2)                      // ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
a.prependAll(Array(0))               // ArrayBuffer(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

val a = ArrayBuffer.range('a', 'h')  // ArrayBuffer(a, b, c, d, e, f, g)
a.remove(0)                          // ArrayBuffer(b, c, d, e, f, g)
a.remove(2, 3)                       // ArrayBuffer(b, c, g)

val a = ArrayBuffer.range('a', 'h')  // ArrayBuffer(a, b, c, d, e, f, g)
a.trimStart(2)                       // ArrayBuffer(c, d, e, f, g)
a.trimEnd(2)                         // ArrayBuffer(c, d, e)

THE LIST CLASS

https://docs.scala-lang.org/overviews/scala-book/list-class.html

List 类是一个线性的、不可变的序列。 所有这一切都意味着它是一个无法修改的链表。 任何时候您想要添加或删除 List 元素,您都可以从现有 List 创建一个新 List。

Creating Lists

这是您创建初始列表的方式:

val ints = List(1, 2, 3)
val names = List("Joel", "Chris", "Ed")

如果您愿意,您也可以声明 List 的类型,但通常没有必要:

val ints: List[Int] = List(1, 2, 3)
val names: List[String] = List("Joel", "Chris", "Ed")

Adding elements to a List

因为 List 是不可变的,所以你不能向它添加新元素。 相反,您可以通过在现有列表中添加或添加元素来创建新列表。 例如,给定这个列表:

val a = List(1,2,3)

您将元素添加到列表中,如下所示:

val b = 0 +: a
val b = List(-1, 0) ++: a

REPL 展示了这是如何工作的:

scala> val b = 0 +: a
b: List[Int] = List(0, 1, 2, 3)

scala> val b = List(-1, 0) ++: a
b: List[Int] = List(-1, 0, 1, 2, 3)

您也可以将元素附加到 List,但是因为 List 是一个单向链表,所以您应该只在它前面添加元素; 向其中添加元素是一个相对较慢的操作,尤其是在处理大型序列时。

提示:如果您想在不可变序列中添加和附加元素,请改用 Vector。

因为 List 是一个链表类,你不应该尝试通过索引值访问大列表的元素。 例如,如果您有一个包含一百万个元素的 List,那么访问像 myList(999999) 这样的元素将需要很长时间。 如果要访问这样的元素,请改用 Vector 或 ArrayBuffer。

How to remember the method names

如今,IDE 为我们提供了极大的帮助,但是记住这些方法名称的一种方法是认为 : 字符代表序列所在的一侧,因此当您使用 +: 时,您知道列表需要在右侧 , 像这样:

 0 +: a

同样,当您使用 :+ 时,您知道列表需要在左侧:

a :+ 4

有更多的技术方法可以考虑这一点,这可以是一种记住方法名称的简单方法。

这些方法名称的一个好处是:它们是一致的。 相同的方法名称用于其他不可变序列类,例如 Seq 和 Vector。

How to loop over lists

我们在本书前面展示了如何循环列表,但值得再次展示语法。 给定一个这样的列表:

val names = List("Joel", "Chris", "Ed")

您可以像这样打印每个字符串:

for (name <- names) println(name)

这是它在 REPL 中的样子:

scala> for (name <- names) println(name)
Joel
Chris
Ed

这种方法的一大优点是它适用于所有序列类,包括 ArrayBuffer、List、Seq、Vector 等。

A little bit of history

如果您对一点历史感兴趣,List 类与 Lisp 编程语言中的 List 类非常相似。 事实上,除了像这样创建一个列表:

val ints = List(1, 2, 3)

您也可以通过这种方式创建完全相同的列表:

val list = 1 :: 2 :: 3 :: Nil

The REPL shows how this works:

scala> val list = 1 :: 2 :: 3 :: Nil
list: List[Int] = List(1, 2, 3)

这是有效的,因为 List 是一个以 Nil 元素结尾的单向链表。

THE VECTOR CLASS

https://docs.scala-lang.org/overviews/scala-book/vector-class.html

Vector 类是一个索引的、不可变的序列。 描述的“索引”部分意味着您可以通过索引值非常快速地访问 Vector 元素,例如访问 listOfPeople(999999)。

一般来说,除了 Vector 有索引而 List 没有索引的区别外,这两个类的工作方式相同,因此我们将快速浏览这些示例。

以下是创建 Vector 的几种方法:

val nums = Vector(1, 2, 3, 4, 5)

val strings = Vector("one", "two")

val peeps = Vector(
    Person("Bert"),
    Person("Ernie"),
    Person("Grover")
)

因为 Vector 是不可变的,所以你不能向它添加新元素。 相反,您可以通过向现有 Vector 附加或预先添加元素来创建新序列。 例如,给定这个向量:

val a = Vector(1,2,3)

你附加这样的元素:

val b = a :+ 4
val b = a ++ Vector(4, 5)

The REPL shows how this works:

scala> val a = Vector(1,2,3)
a: Vector[Int] = Vector(1, 2, 3)

scala> val b = a :+ 4
b: Vector[Int] = Vector(1, 2, 3, 4)

scala> val b = a ++ Vector(4, 5)
b: Vector[Int] = Vector(1, 2, 3, 4, 5)

您还可以预先添加这样的元素:

val b = 0 +: a
val b = Vector(-1, 0) ++: a

REPL 再次展示了这是如何工作的:

scala> val b = 0 +: a
b: Vector[Int] = Vector(0, 1, 2, 3)

scala> val b = Vector(-1, 0) ++: a
b: Vector[Int] = Vector(-1, 0, 1, 2, 3)

因为 Vector 不是链表(如 List),您可以在其前面添加和附加元素,并且两种方法的速度应该相似。

最后,您可以像处理 ArrayBuffer 或 List 一样遍历 Vector 中的元素:

scala> val names = Vector("Joel", "Chris", "Ed")
val names: Vector[String] = Vector(Joel, Chris, Ed)

scala> for (name <- names) println(name)
Joel
Chris
Ed

THE MAP CLASS

https://docs.scala-lang.org/overviews/scala-book/map-class.html

Map 类文档将 Map 描述为由键和值对组成的可迭代序列。 一个简单的 Map 如下所示:

val states = Map(
    "AK" -> "Alaska",
    "IL" -> "Illinois",
    "KY" -> "Kentucky"
)

Scala 有可变和不可变的 Map 类。 在本课中,我们将展示如何使用可变类。

Creating a mutable Map

要使用可变 Map 类,首先导入它:

import scala.collection.mutable.Map

然后你可以像这样创建一个Map:

val states = collection.mutable.Map("AK" -> "Alaska")

Adding elements to a Map

现在您可以使用 += 向 Map 添加单个元素,如下所示:

states += ("AL" -> "Alabama")

您还可以使用 += 添加多个元素:

states += ("AR" -> "Arkansas", "AZ" -> "Arizona")

您可以使用 ++= 从另一个 Map 添加元素:

states ++= Map("CA" -> "California", "CO" -> "Colorado")

The REPL shows how these examples work:

scala> val states = collection.mutable.Map("AK" -> "Alaska")
states: scala.collection.mutable.Map[String,String] = Map(AK -> Alaska)

scala> states += ("AL" -> "Alabama")
res0: states.type = Map(AL -> Alabama, AK -> Alaska)

scala> states += ("AR" -> "Arkansas", "AZ" -> "Arizona")
res1: states.type = Map(AZ -> Arizona, AL -> Alabama, AR -> Arkansas, AK -> Alaska)

scala> states ++= Map("CA" -> "California", "CO" -> "Colorado")
res2: states.type = Map(CO -> Colorado, AZ -> Arizona, AL -> Alabama, CA -> California, AR -> Arkansas, AK -> Alaska)

Removing elements from a Map

您可以使用 -= 和 --= 并指定键值从 Map 中删除元素,如以下示例所示:

states -= "AR"
states -= ("AL", "AZ")
states --= List("AL", "AZ")

The REPL shows how these examples work:

scala> states -= "AR"
res3: states.type = Map(CO -> Colorado, AZ -> Arizona, AL -> Alabama, CA -> California, AK -> Alaska)

scala> states -= ("AL", "AZ")
res4: states.type = Map(CO -> Colorado, CA -> California, AK -> Alaska)

scala> states --= List("AL", "AZ")
res5: states.type = Map(CO -> Colorado, CA -> California, AK -> Alaska)

Updating Map elements

您可以通过将它们的键重新分配给新值来更新 Map 元素:

states("AK") = "Alaska, A Really Big State"

The REPL shows the current Map state:

scala> states("AK") = "Alaska, A Really Big State"

scala> states
res6: scala.collection.mutable.Map[String,String] = Map(CO -> Colorado, CA -> California, AK -> Alaska, A Really Big State)

Traversing a Map

有几种不同的方法可以迭代映射中的元素。Given a sample map:

val ratings = Map(
    "Lady in the Water"-> 3.0, 
    "Snakes on a Plane"-> 4.0,
    "You, Me and Dupree"-> 3.5
)

循环遍历所有地图元素的一个好方法是使用for循环语法:

for ((k,v) <- ratings) println(s"key: $k, value: $v")

foreach方法中使用match也非常易读:

ratings.foreach {
    case(movie, rating) => println(s"key: $movie, value: $rating")
}

See also

还有其他方法可以使用 Scala Maps,以及满足不同需求的 Map 类的一个很好的集合。 有关更多信息和示例,请参阅 Map 类文档

THE SET CLASS

https://docs.scala-lang.org/overviews/scala-book/set-class.html

Scala Set 类是一个没有重复元素的可迭代集合。

Scala 有可变和不可变的 Set 类。 在本课中,我们将展示如何使用可变类。

Adding elements to a Set

要使用可变 Set,首先导入它:

val set = scala.collection.mutable.Set[Int]()

您可以使用 +=、++= 和 add 方法将元素添加到可变 Set 中。 这里有一些例子:

set += 1
set += 2 += 3
set ++= Vector(4, 5)

The REPL shows how these examples work:

scala> val set = scala.collection.mutable.Set[Int]()
val set: scala.collection.mutable.Set[Int] = Set()

scala> set += 1
val res0: scala.collection.mutable.Set[Int] = Set(1)

scala> set += 2 += 3
val res1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)

scala> set ++= Vector(4, 5)
val res2: scala.collection.mutable.Set[Int] = Set(1, 5, 2, 3, 4Scala 学习之「类——基本概念2」

Scala学习之TRAITS和抽象类

Scala入门学习之包类与对象

Scala 学习之「trait 」

Scala 模式匹配详解

Scala 学习之面向对象