Scala에서 immutable.Map을 mutable.Map으로 어떻게 변환 할 수 있습니까?


93

어떻게 변환 할 수 있습니다 immutable.Mapmutable.Map에 내가 값을 업데이트 할 수 있도록 스칼라 Map?

답변:


126

가장 깨끗한 방법은 mutable.Mapvarargs 공장 을 사용하는 것 입니다. ++접근 방식 과 달리 이것은 CanBuildFrom메커니즘을 사용 하므로이를 활용하기 위해 라이브러리 코드를 작성하면 더 효율적일 수 있습니다.

val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*) 

이것은 Map쌍의 시퀀스로도 볼 수 있기 때문에 작동합니다 .


2
매개 변수를 전달할 때 두 번째 줄에서 사용하는 구문을 설명해 주시겠습니까? 콜론은 무엇을합니까?
Heinzi

7
: _*컴파일러에게 주어진 표현식에 어떤 유형을 할당할지 정확히 알려주는 유형 지정과 매우 유사합니다. 여기서 "이 시퀀스를 가져 와서 여러 vararg 매개 변수로 취급"이라고 생각할 수 있습니다.
Kevin Wright

16
이것이 가장 깨끗한 경우 컬렉션 라이브러리에 문제가있는 것입니다;)
matanster

2
@matt 별칭 가져 오기를 사용하면 약간 더 짧게 만들 수 있지만, 불변성을 희생 하는 것은 Scala에게 매우 비관 상적이라는 점을 명심하십시오. , 사본이 아니라면 어떻게 더 깔끔하게 할 것을 제안 할 수 있습니까?
Kevin Wright

그게 내 요점이지만 할 수는 없지만 더 나은 컬렉션 라이브러리가 IMHO를 가능하게 할 수 있습니다.
matanster 2015

41
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap

1
이것의 점근 적 시간 복잡성이 모자라는 것을 알고 있습니까? Clojure는 영구 컬렉션을 "일시적인"컬렉션 (즉, 선형 유형의 돌연변이 함수를 가진 가변 컬렉션)으로 전환하고 O(1)단계적 으로 영구 컬렉션으로 되돌릴 수 있다는 것을 알고 있습니다 . 이 외모 가 될 O(n)그 얼마나 영리 구현에 당연히 달려 있지만, ++있다.
Jörg W Mittag

1
@ Jörg-나는 이것이 O(n). O(n)시간을 절약하기 위해 새 사본의 생성을 연기하거나 원래 맵 대신 변경 세트를 읽어 액세스 시간을 두 배로 늘릴 수 있지만 모든 것을 변경할 때 한계는이어야합니다 . 어느 것이 가장 잘 수행되는지는 아마도 사용 사례에 따라 다릅니다.
Rex Kerr

1
@Rustem-지도가 순서가 지정되지 않았습니다. 원하는 순서대로 표시됩니다 (해시 맵의 경우 일반적으로 해시 키의 순서입니다). 특히, 불변 맵은 변경 가능한 맵과 다른 아주 작은 맵에 대한 특별한 경우를 가지고 있습니다.
Rex Kerr

@Rustem Maps는 주문되지 않았습니다.
Daniel C. Sobral

4

collection.breakOut을 사용하는 것은 어떻습니까?

import collection.{mutable, immutable, breakOut}
val myImmutableMap = immutable.Map(1->"one",2->"two")
val myMutableMap: mutable.Map[Int, String] = myImmutableMap.map(identity)(breakOut)

그것은 이다 멋진하지만, 같이 기본적으로 같은 일을 mutable.Map#applyA가 더 상용구 비트와.
Kevin Wright

4

시작 Scala 2.13, .to(factory)다음 과 함께 적용된 팩토리 빌더를 통해 :

Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")

1

Mapimmutable에서 가져온 기본값을 가진 빈 mutable을 만드는 변형이 있습니다 Map. 언제든지 값을 저장하고 기본값을 재정의 할 수 있습니다.

scala> import collection.immutable.{Map => IMap}
//import collection.immutable.{Map=>IMap}

scala> import collection.mutable.HashMap
//import collection.mutable.HashMap

scala> val iMap = IMap(1 -> "one", 2 -> "two")
//iMap: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two))

scala> val mMap = new HashMap[Int,String] {      
     | override def default(key: Int): String = iMap(key)
     | }
//mMap: scala.collection.mutable.HashMap[Int,String] = Map()

scala> mMap(1)
//res0: String = one

scala> mMap(2)
//res1: String = two

scala> mMap(3)
//java.util.NoSuchElementException: key not found: 3
//  at scala.collection.MapLike$class.default(MapLike.scala:223)
//  at scala.collection.immutable.Map$Map2.default(Map.scala:110)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)
//  at scala.collection.immutable.Map$Map2.apply(Map.scala:110)
//  at $anon$1.default(<console>:9)
//  at $anon$1.default(<console>:8)
//  at scala.collection.MapLike$class.apply(MapLike.scala:134)....

scala> mMap(2) = "three"

scala> mMap(2)          
//res4: String = three

주의 사항 (Rex Kerr의 주석 참조) : 변경 불가능한 맵에서 오는 요소를 제거 할 수 없습니다.

scala> mMap.remove(1)
//res5: Option[String] = None

scala> mMap(1)
//res6: String = one

3
이는 경우에 따라 유용하지만 기본지도에 있던 새지도에서 요소를 제거 할 수 없습니다. 기본값을 덮고 폭로 할 수만 있습니다.
Rex Kerr

맞습니다,이 솔루션은 부분적입니다.
Alexander Azarov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.