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 集合类是:
Class | Description |
---|---|
ArrayBuffer | 一个索引的、可变的序列 |
List | 线性(链表),不可变序列 |
Vector | 一个索引的、不可变的序列 |
Map | 基础Map (键/值对)类 |
Set | 基础Set 类 |
Map
和 Set
有可变和不可变版本。
我们将在以下课程中演示这些课程的基础知识。
在以下有关 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」