如何声明空列表,然后在Scala中添加字符串?


81

我有这样的代码:

val dm  = List[String]()
val dk = List[Map[String,Object]]()

.....

dm.add("text")
dk.add(Map("1" -> "ok"))

但是会抛出运行时java.lang.UnsupportedOperationException。

我需要声明一个空列表或空地图,并且在代码的后面部分需要填充它们。


是什么让您认为可以进行add手术List
Debilski

如果要使用添加操作,则必须声明一个ArrayList。Scala中的Val本质上是不可变的,因此您不能添加它们。
Phantom73

1
iirc val更像final,如果您使用可变集合,则可以将其添加到它们中。例如scala-lang.org/api/current/scala/collection/mutable/…–
DaVinci

1
@rjc您正在使用哪个版本的scala?我的(2.9.0)给我一个编译错误。
范式

4
你进口了scala.collection.JavaConversions吗?如果你没有,你所看到的这个理由,我建议JavaConverters改为:dmdk被转换成Java集合,然后add叫上采集方法。更糟的是,dmdk没有被修改,即使你没有得到一个错误。而且,顺便说一句,错误1 -> "ok"Map[Int,String],不是Map[String, Object]
Daniel C. Sobral

Answers:


117

Scala列表默认是不可变的。您不能“添加”元素,但是可以通过在前面附加新元素来形成新列表。由于这是一个列表,因此您需要重新分配引用(因此您不能使用val)。

var dm  = List[String]()
var dk = List[Map[String,AnyRef]]()

.....

dm = "text" :: dm
dk = Map(1 -> "ok") :: dk

操作员::创建新列表。您还可以使用较短的语法:

dm ::= "text" 
dk ::= Map(1 -> "ok")

注:在Scala中不使用的类型Object,但是AnyAnyRef还是AnyVal


很好的答案,但是您能告诉我是否像您的答案一样声明列表,它们是scala.collections.mutable类型还是不可变类型?REPL没有明确说明。
rjc 2011年

2
默认。如果不导入任何内容。List是一成不变的。这是推荐用于大多数用途的一种。
范式

11
@rjc Scala没有mutable.List-List是具体类型,唯一的实现是不可变的。有不可变的类,例如LinkedListDoubleLinkedList,大多数是辅助类。斯卡拉相当于Java的的ArrayListArrayBuffer,和Java的相当于LinkedListListBuffer。与Java相对应的特征ListSeq-具有,collection.Seq并且扩展了Javacollection.immutable.Seqcollection.mutable.Seq
Daniel C. Sobral

@paradigmatic::=和之间有区别+=吗?
Mahdi 2015年

@Mahdi可能有所不同。仅在列表::中定义,因此+=将不起作用。在其他集合(不是在标准库):如果::=+=实施,实施将被使用。否则,编译器将x::=y变成x = y::xx+=yinro x=x+y。在第二种情况下,他们如果执行同样的::相同的实施+...
范式

17

如果您需要更改内容,请使用ArrayBufferLinkedBuffer代替。但是,最好处理以下语句:

我需要声明一个空列表或空地图,并且在代码的后面部分需要填充它们。

而不是这样做,而是使用返回元素的代码填充列表。有很多方法可以做到这一点,我将举一些例子:

// Fill a list with the results of calls to a method
val l = List.fill(50)(scala.util.Random.nextInt)

// Fill a list with the results of calls to a method until you get something different
val l = Stream.continually(scala.util.Random.nextInt).takeWhile(x => x > 0).toList

// Fill a list based on its index
val l = List.tabulate(5)(x => x * 2)

// Fill a list of 10 elements based on computations made on the previous element
val l = List.iterate(1, 10)(x => x * 2)

// Fill a list based on computations made on previous element, until you get something
val l = Stream.iterate(0)(x => x * 2 + 1).takeWhile(x => x < 1000).toList

// Fill list based on input from a file
val l = (for (line <- scala.io.Source.fromFile("filename.txt").getLines) yield line.length).toList

14

正如大家已经提到的那样,这不是在Scala中使用列表的最佳方法。

scala> val list = scala.collection.mutable.MutableList[String]()
list: scala.collection.mutable.MutableList[String] = MutableList()

scala> list += "hello"
res0: list.type = MutableList(hello)

scala> list += "world"
res1: list.type = MutableList(hello, world)

scala> list mkString " "
res2: String = hello world

您能否说出您的列表是否像答案中那样声明,与范式答案相比,它会提供更好的运行时性能吗?假设将在列表中添加数百万个元素。
rjc 2011年

这取决于您要实现的目标。我建议从@paradigmatic建议的不可变的开始。像这样将元素添加到不可变列表的复杂性list ::= "text"是O(1),它是常量,是您可以做的最好的事情。
agilesteel 2011年

rjc:不可变列表的缺点是O(1); 但是,真正重要的是就效率而言的访问模式。例如,如果顺序很重要,并且您必须通过追加来构建列表,则Vector是更好的选择(不可变)。
Kris Nuttycombe

6

如上面的答案所述,Scala列表是一个不可变的集合。您可以使用创建一个空列表.empty[A]。然后,您可以使用方法:++:::为了将元素添加到列表中。

scala> val strList = List.empty[String]
strList: List[String] = List()

scala> strList:+ "Text"
res3: List[String] = List(Text)

scala> val mapList = List.empty[Map[String, Any]]
mapList: List[Map[String,Any]] = List()

scala> mapList :+ Map("1" -> "ok")
res4: List[Map[String,Any]] = List(Map(1 -> ok))


0

也许您可以在scala中使用ListBuffers创建空列表并稍后添加字符串,因为ListBuffers是可变的。而且,所有列表函数都可用于scala中的ListBuffers。

import scala.collection.mutable.ListBuffer 

val dm = ListBuffer[String]()
dm: scala.collection.mutable.ListBuffer[String] = ListBuffer()
dm += "text1"
dm += "text2"
dm = ListBuffer(text1, text2)

如果需要,可以使用.toList将其转换为列表


0

在您的情况下,我使用:val dm = ListBuffer[String]()val dk = ListBuffer[Map[String,anyRef]]()

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.