빈 목록을 선언 한 다음 스칼라에 문자열을 추가하는 방법은 무엇입니까?


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 2011

추가 작업을 사용하려면 ArrayList를 선언해야합니다. 스칼라의 Val은 본질적으로 불변이므로 추가 할 수 없습니다.
Phantom73 2011

1
iirc val은 final과 비슷합니다. 변경 가능한 컬렉션을 사용하면 추가 할 수 있습니다. 예 : scala-lang.org/api/current/scala/collection/mutable/…
DaVinci

1
@rjc 어떤 버전의 스칼라를 사용하고 있습니까? 내 (2.9.0) 컴파일 오류가 발생합니다.
패러다임

4
수입 했습니까 scala.collection.JavaConversions? 당신이 한 경우에, 당신은 내가 추천하는 이유는 바로 그 이유보고있다 JavaConverters: 대신 dm하고 dk다음 자바 콜렉션으로 전환되고 있으며, add그 컬렉션이라는 방법을. 더 나쁜, dm그리고는 dk당신이 오류가 발생하지 않은 경우에도 수정되지 않습니다. 그리고, 그런데, 오류가 즉 1 -> "ok"있다 Map[Int,String], 없다 Map[String, Object].
Daniel C. Sobral 2011

답변:


117

스칼라 목록은 기본적으로 변경할 수 없습니다. 요소를 "추가"할 수 없지만 앞에 새 요소를 추가하여 새 목록을 만들 수 있습니다. 그것이이기 때문에 새로운 목록, 당신은 (당신이 발을 사용할 수 있도록) 참조를 다시 할당해야합니다.

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

.....

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

운영자 ::는 새 목록을 만듭니다. 더 짧은 구문을 사용할 수도 있습니다.

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

NB : 에이 형식을 사용하지 않는 스칼라 Object하지만 Any, AnyRef또는 AnyVal.


아주 좋은 대답이지만 대답과 같이 목록을 선언하는지 알 수 있습니까? scala.collections.mutable 또는 immutable 유형입니까? REPL은 이것을 명확히하지 않았습니다.
rjc

2
기본적으로. 아무것도 가져 오지 않으면. List불변입니다. 대부분의 사용에 권장되는 것입니다.
패러다임

11
@rjc Scala에는 mutable.List- List가없는 구체적인 유형이며 유일한 구현은 변경할 수 없습니다. 같은 불변 클래스가 있습니다 LinkedListDoubleLinkedList대부분의 헬퍼 클래스입니다. Java에 해당하는 Scala ArrayListArrayBuffer이고 Java에 해당하는 LinkedList것은 ListBuffer. 형질 자바의에 해당이 있다는 List것입니다 Seq- 어느 거기 collection.Seq를 확장하고, collection.immutable.Seq하고 collection.mutable.Seq.
Daniel C. Sobral

차이가있다 @paradigmatic ::=+=?
Mahdi

@Mahdi 차이가있을 수 있습니다. 목록에서만 ::정의되므로 +=작동하지 않습니다. 다른 컬렉션 (표준 라이브러리가 아님) : ::=또는 +=구현 된 경우 구현이 사용됩니다. 그 밖에, 컴파일러는 켜집니다 x::=yx = y::x하고 x+=yinro x=x+y. 두 번째 경우 ::의 구현이 +... 의 구현과 동일하면 동일합니다 .
패러다임

17

항목을 변경해야하는 경우 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

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

달성하려는 목표에 따라 다릅니다. @paradigmatic이 제안한 것처럼 불변의 것으로 시작하는 것이 좋습니다. 다음과 같이 변경 불가능한 목록에 요소를 추가하는 데 list ::= "text"따르는 복잡성 은 O (1)이며 이는 일정하며 최선을 다합니다.
agilesteel

rjc : 불변 목록의 단점은 O (1); 그러나 실제로 중요한 것은 효율성에 관한 한 액세스 패턴입니다. 예를 들어 순서가 중요하고 추가하여 목록을 작성해야하는 경우 Vector가 더 나은 (불변) 선택입니다.
Kris Nuttycombe 2011

6

이상에서 언급 한 바와 같이 대답스칼라 목록 불변의 모음입니다. 를 사용하여 빈 목록을 만들 수 있습니다 .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

스칼라에서 ListBuffers를 사용하여 빈 목록을 만들고 나중에 문자열을 추가 할 수 있습니다. ListBuffer는 변경 가능하기 때문입니다. 또한 모든 List 함수는 스칼라의 ListBuffer에 사용할 수 있습니다.

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]]()

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.