35

我正在运行 Scala 2.10.2。我想创建一个列表,然后将一些元素添加到列表中,并希望在调用列表名称时看到列表中的所有元素。但我观察到一些很奇怪的事情(至少对我来说很奇怪,因为我是新手)。以下是我尝试在我的sbt console

scala> val l = 1.0 :: 5.5 :: Nil
l: List[Double] = List(1.0, 5.5)

scala> l
res0: List[Double] = List(1.0, 5.5)

scala> l ::: List(2.2, 3.7)
res1: List[Double] = List(1.0, 5.5, 2.2, 3.7)

scala> List(l) :+ 2.2
res2: List[Any] = List(List(1.0, 5.5), 2.2)

scala> l
res3: List[Double] = List(1.0, 5.5)

scala> 

首先,我创建了l包含 2 个元素(1.0 和 5.5)的列表。我打电话l得到我所期望的;这两个元素。现在我尝试将另一个元素添加到列表中,使用:::它返回一个新列表,其中包含我添加的新元素列表(2.2 和 3.7)甜蜜!我什至检查了别人的代码以寻求帮助:在 Scala 中将元素附加到列表的末尾以使用新的构造:+。所以在这个阶段我很高兴,但我打电话l并得到了意想不到的结果:`res3: List[Double] = List(1.0, 5.5)'。

我添加的元素在哪里?以及如何正确添加这些元素,以便在调用时l获得一个包含所有添加内容的新列表?

4

4 回答 4

46

您正在使用不可变列表。对 List 的操作返回一个新的 List。旧列表保持不变。如果另一个类/方法持有对原始集合的引用并且依赖它保持不变,这将非常有用。您可以使用不同的命名值,如

val myList1 = 1.0 :: 5.5 :: Nil 
val myList2 = 2.2 :: 3.7 :: mylist1

或使用 var ,如

var myList = 1.0 :: 5.5 :: Nil 
myList :::= List(2.2, 3.7)

这是等效的语法:

myList = myList.:::(List(2.2, 3.7))

或者您可以使用其中一个可变集合,例如

val myList = scala.collection.mutable.MutableList(1.0, 5.5)
myList.++=(List(2.2, 3.7))

不要与以下不修改原始可变列表但返回新值的内容混淆:

myList.++:(List(2.2, 3.7))

但是,您应该只在性能关键代码中使用可变集合。不可变集合更容易推理和使用。一大优势是不可变 List 和scala.collection.immutable.Vector是协变的。如果这对您还没有任何意义,请不要担心。它的优点是您可以在不完全理解它的情况下使用它。因此,您默认使用的集合实际上是scala.collection.immutable.List它只是自动为您导入的。

我倾向于使用 List 作为我的默认集合。从 2.12.6 Seq 默认为不可变 Seq 在此之前它默认为不可变。

于 2013-10-26T18:50:31.363 回答
12

如果您确实需要突变,请使用import scala.collection.mutable.MutableList或类似方法。

import scala.collection.mutable.MutableList
val x = MutableList(1, 2, 3, 4, 5)
x += 6 // MutableList(1, 2, 3, 4, 5, 6)
x ++= MutableList(7, 8, 9) // MutableList(1, 2, 3, 4, 5, 6, 7, 8, 9)
于 2013-10-26T18:50:39.897 回答
8

我将尝试解释您尝试的所有命令的结果。

scala> val l = 1.0 :: 5.5 :: Nil
l: List[Double] = List(1.0, 5.5)

首先,List是一个类型别名scala.collection.immutable.List(在 Predef.scala 中定义)。

使用 List 伴随对象是实例化List. 前任:List(1.0,5.5)

scala> l
res0: List[Double] = List(1.0, 5.5)

scala> l ::: List(2.2, 3.7)
res1: List[Double] = List(1.0, 5.5, 2.2, 3.7)

:::返回由给定列表前缀和此列表的串联产生的列表

原始列表未修改

scala> List(l) :+ 2.2
res2: List[Any] = List(List(1.0, 5.5), 2.2)

List(l)绝对List[List[Double]]不是你想要的。

:+返回一个新列表,该列表由该列表的所有元素组成,后跟 elem。

该类型是List[Any]因为它是和之间的公共超List[Double]Double

scala> l
res3: List[Double] = List(1.0, 5.5)

l 保持不变,因为没有immutable.List修改列表的方法。

于 2013-10-27T10:19:25.590 回答
2

由于您想将元素附加到现有列表中,您可以使用 var List[Int] 然后继续将元素添加到同一个列表中。注意->您必须确保将元素插入到现有列表中,如下所示:-

var l: List[int] = List() // 创建一个空列表

l = 3 :: l // 将 3 添加到列表的头部

l = 4 :: l // 使 int 4 作为列表的头部

// 现在当你打印 l 时,你会在列表中看到两个元素 (4, 3)

于 2016-10-23T20:55:15.680 回答