Как объявить пустой список, а затем добавить строку в Scala?


У меня есть такой код:

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

.....

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

но он бросает Java во время выполнения.ленг.Возникновению unsupportedoperationexception.

Мне нужно объявить пустой список или пустые карты, где в коде нужно будет их заполнить.

7 65

7 ответов:

списки 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 но Any,AnyRef или AnyVal.

Если вам нужно мутировать вещи, использовать ArrayBuffer или LinkedBuffer вместо. Тем не менее, было бы лучше обратиться к этому заявлению:

мне нужно объявить пустой список или пустой карты и кое-где позже в коде нужно их заполнить.

вместо этого заполните список кодом, который возвращает элементы. Есть много способов сделать это, и я приведу несколько примеров:

// 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

Как все уже упоминали, это не лучший способ использования списков в 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

по умолчанию коллекции в scala неизменяемы, поэтому у вас есть метод+, который возвращает новый список с добавленным в него элементом. Если вам действительно нужно что - то вроде метода add, вам нужна изменяемая коллекция, например http://www.scala-lang.org/api/current/scala/collection/mutable/MutableList.html который имеет + = метод.

Как упоминалось выше ответ на Scala List является неизменяемой коллекцией. Вы можете создать пустой список .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))

возможно, вы можете использовать ListBuffers в scala для создания пустого списка и добавления строк позже, потому что ListBuffers изменчивы. Также все функции списка доступны для ListBuffers в scala.

import scala.collection.mutable.ListBuffer 

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

Если вы хотите, вы можете преобразовать это в список с помощью .список

в вашем случае я использую: val dm = ListBuffer[String]() и val dk = ListBuffer[Map[String,anyRef]]()