2011-07-02 10 views
58

mam kod jak poniżej:Jak zadeklarować pustą listę, a następnie dodać ciąg znaków w scala?

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

..... 

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

ale rzuca wykonania java.lang.UnsupportedOperationException.

Muszę zadeklarować pustą listę lub puste mapy, a niektóre gdzie później w kodzie trzeba je wypełnić.

+0

Co sprawia, że ​​myślisz, że istnieje operacja 'add' na liście' List'? – Debilski

+0

Jeśli chcesz użyć operacji dodawania, musisz zadeklarować ArrayList. Vals in scala są w zasadzie niezmienne, więc nie możesz ich dodać. – Phantom73

+1

iirc val jest bardziej podobny do ostatecznego, możesz do niego dodać, jeśli używasz zmiennych kolekcji. na przykład http://www.scala-lang.org/api/current/scala/collection/mutable/MutableList.html – DaVinci

Odpowiedz

86

Listy Scala są domyślnie niezmienne. Nie można "dodać" elementu, ale można utworzyć nową listę, dołączając nowy element z przodu. Ponieważ jest to nowa lista, należy ponownie przypisać odwołanie (aby nie można było użyć wartości val).

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

..... 

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

Operator tworzy nową listę operator ::. Można również skorzystać z krótszą składnię:

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

UWAGA: w Scala nie użyć typu Object ale Any, AnyRef lub AnyVal.

+0

Bardzo dobra odpowiedź, ale czy możesz powiedzieć, czy deklaruję listę tak jak w Twojej odpowiedzi, czy są one typu scala.collections.mutable lub immutable type? REPL nie wyjaśniło tego. – rjc

+2

Domyślnie. Jeśli nic nie importujesz. "Lista" jest niezmienna. Jest to zalecany do większości zastosowań. – paradigmatic

+11

@rjc Scala nie ma 'mutable.List' -' List' jest konkretnym typem, którego jedyna implementacja jest niezmienna. Istnieją niezmienne klasy, takie jak 'LinkedList' i' DoubleLinkedList', które są w większości klasami pomocniczymi. Odpowiednikiem Scala Java 'ArrayList' jest' ArrayBuffer', a odpowiednikiem 'LinkedList' języka Java jest' ListBuffer'. Cechą, która odpowiada "liście" Javy jest "Seq" - której jest 'collection.Seq' oraz, rozszerzając go,' collection.immutable.Seq' oraz 'collection.mutable.Seq'. –

11

Jak każdy już wspomniano, nie jest najlepszym sposobem korzystania z list w 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 
+0

Czy możesz stwierdzić, czy twoja lista jest zadeklarowana tak jak w twojej odpowiedzi, czy zapewni lepszą wydajność środowiska wykonawczego? w przeciwieństwie do odpowiedzi paradygmatycznej? Załóżmy, że na liście zostaną dodane miliony elementów. – rjc

+0

To zależy od tego, co próbujesz osiągnąć. Polecam zacząć od niezmiennego, jak sugerował @paradigmatic. Złożoność dodawania elementu do niezmiennej listy, takiej jak ta: 'list :: =" text "' to O (1), która jest stała i najlepsza co możesz zrobić. – agilesteel

+0

rjc: minus niezmiennych list to O (1); jednak najważniejszy jest twój wzorzec dostępu, jeśli chodzi o efektywność. Na przykład, jeśli zamówienie ma znaczenie i musisz zbudować listę przez dołączenie, wektor jest lepszym (niezmiennym) wyborem. –

16

Jeśli trzeba zmutować rzeczy, użyj ArrayBuffer lub LinkedBuffer zamiast. Jednak byłoby lepiej, aby rozwiązać ten oświadczenie:

muszę zadeklarować pustą listę lub pustych mapy i gdzieś później w kodzie trzeba je wypełnić.

Zamiast tego, wypełnij listę kodem, który zwraca elementy. Istnieje wiele sposobów, aby to uczynić, a dam kilka przykładów:

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

Być może używać ListBuffers w Scala, aby utworzyć pustą listę i dodawać ciągi później bo ListBuffers są zmienne. Również wszystkie funkcje List są dostępne dla ListBufferów w 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) 

jeśli chcesz można przekonwertować to do listy za pomocą .toList

0

W twoim przypadku używam: val dm = ListBuffer[String]() i val dk = ListBuffer[Map[String,anyRef]]()

0

Jak wspomniano w powyższym answer The Scala List jest niezmienna kolekcja. Możesz utworzyć pustą listę z .empty[A]. Następnie możesz użyć metody :+, +: lub :: w celu dodania elementu do listy.

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)) 
Powiązane problemy