scala学习之scala集合类(代码片段)

顧棟 顧棟     2022-12-18     603

关键词:

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, 4查看详情  

scala学习之scala中的类(代码片段)

文章目录SCALACLASSESBasicclassconstructor`val`makesfieldsread-onlyClassconstructorsOtherScalaclassexamplesAUXILIARYCLASSCONSTRUCTORSNotesSUPPLYINGDEFAULTVALUESFORCONSTRUCTORPARAMETERSBenefitsBonus 查看详情

scala的继承和抽象类(代码片段)

...ala系列学习笔记:Scala概述与开发环境配置Scala基础学习之运算符Scala基础学习之for循环和while循环一文掌握scala中的方法和函数Scala基础:类和对象、访问修饰符和构造器本章节目标掌握继承和抽象类相关知识点掌握匿名... 查看详情

scala学习之「类——基本概念2」(代码片段)

目录内部类extendsoverride和superoverridefieldisInstanceOf和asInstanceOfgetClass和classOf内部类importscala.collection.mutable.ArrayBufferclassClassclassStudent(valname:String)//此处为内部类valstudents=newArrayBuffer[Student]defgetStudent(name:String)=newStudent(name)valc1=newClassval... 查看详情

scala学习之函数式风格编程(代码片段)

FUNCTIONALPROGRAMMINGhttps://docs.scala-lang.org/overviews/scala-book/functional-programming.htmlScala允许您以面向对象编程(OOP)风格、函数式编程(FP)风格甚至混合风格编写代码,结合使用这两种方法。本书假设您是从Java、C++或C#等OOP语言来... 查看详情

scala学习之tuples和oop示例(代码片段)

文章目录AFEWMISCELLANEOUSITEMSTUPLESAfewmoretupledetailsReturningatuplefromamethodTuplesaren’tcollectionsANOOPEXAMPLEAfewclassesAddingbehaviortoPizzaAddingbehaviortoOrderTestingthoseclassesExperimentwitht 查看详情

scala学习之「trait」(代码片段)

trait调用链Scala中支持让类继承多个trait后,依次调用多个trait中的同一个方法,只要让多个trait的同一个方法中,在最后都执行super.方法即可类中调用多个trait中都有的这个方法时,首先会从最右边的trait的方法开始执行,然后依... 查看详情

scala深入学习之函数学习(代码片段)

目录一、函数的定义二、匿名函数三、递归函数四、无参函数五、方法和函数的区别联系一、函数的定义代码示例:packagefunctionDemo/***@author:蔡政洁*@email:caizhengjie888@icloud.com*@date:2020/8/23*@time:2:14下午*/objectFunction... 查看详情

scala基础语法之trait详解(代码片段)

...ala系列学习笔记:Scala概述与开发环境配置Scala基础学习之运算符Scala基础学习之for循环和while循环一文掌握scala中的方法和函数Scala基础:类和对象、访问修饰符和构造器Scala的继承和抽象类本章节目标能够使用trait独立完... 查看详情

scala学习之面向对象

==> 类        ---> 类的定义class Student{    // 定义属性    private var stuName:String = 查看详情

scala数据结构(代码片段)

一、概述1,特点1)Scala同时支持不可变集合和可变集合2)两个主要的包:不可变集合:scala.collection.immutable可变集合:scala.collection.mutable3)Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变(mutable)和不可变(im... 查看详情

scala学习--其他集合类学习(代码片段)

Scala学习--其他集合类学习一、序列列表缓冲ListBufferList类提供对列表头部快速访问,尾部访问并不高效。使用List类在尾部追加元素往往通过reverse,表头添加,reverse实现。通过ListBuffer可以简单实现。ListBuffer是一个可变对象,包... 查看详情

大数据学习之scala语言基本语法学习36

一:scala简介官网:https://www.scala-lang.org/Scala语言很强大,集成了面向对象和函数式编程的特点。运行在JVM(jdk)。大数据中为什么学习scala?spark是scala语言编写。python写spark挺好的java写spark很糟糕(代码实在是太多了)scala写spark很... 查看详情

scala高阶:集合内容汇总(上篇)(代码片段)

@TOCScala中的集合与Java中的集合相类似,但是又有很多的改变,接下来我们开启Scala集合篇的学习历程吧!一、概述在Java中的集合分为三大类:List集合、Set集合、Map集合。其中List集合、Set集合继承自Collection。它们都是接口。Scala... 查看详情

大数据学习之scala中main函数的分析以及基本规则

一、main函数的分析首先来看我们在上一节最后看到的这个程序,我们先来简单的分析一下。有助于后面的学习objectHelloScala{defmain(args:Array[String]):Unit={println("ILoveYouScala");}}如图所看到的,在Scala中能够使用object和class分别定义一个... 查看详情

scala学习之:flattenanestedliststructure

题目要求:(**)Flattenanestedliststructure.Example:scala>flatten(List(List(1,1),2,List(3,List(5,8))))res0:List[Any]=List(1,1,2,3,5,8)参考:http://blog.thedigitalcatonline.com/blog/2015/04/07/99-scala-proble 查看详情

scala基础学习之for循环和while循环(代码片段)

章节目标掌握分支结构的格式和用法掌握for循环和while循环的格式和用法掌握控制跳转语句的用法掌握循环案例理解do.while循环的格式和用法1.流程控制结构1.1概述在实际开发中,我们要编写成千上万行代码,代码的顺序不同,执行结... 查看详情

scala学习之爬豆瓣电影

简单使用Scala和Jsoup对豆瓣电影进行爬虫,技术比較简单易学。写文章不易,欢迎大家採我的文章,以及给出实用的评论,当然大家也能够关注一下我的github;多谢。1、爬虫前期准备找好须要抓取的链接:https://movie.douban.com/tag/%E... 查看详情