Como posso converter immutable.Mappara mutable.Mapno Scala para que eu possa atualizar os valores em Map?
Como posso converter immutable.Mappara mutable.Mapno Scala para que eu possa atualizar os valores em Map?
Respostas:
A maneira mais limpa seria usar a mutable.Mapfábrica de Varargs. Ao contrário da ++abordagem, ele usa o CanBuildFrommecanismo e, portanto, tem o potencial de ser mais eficiente se o código da biblioteca foi escrito para tirar proveito disso:
val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*)
Isso funciona porque a Maptambém pode ser visto como uma sequência de pares.
: _*é muito parecido com a atribuição de tipo, dizendo ao compilador exatamente que tipo atribuir a uma determinada expressão. Você pode pensar nisso aqui como dizer "pegue esta sequência e trate-a como uma série de parâmetros vararg."
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap
O(1)etapas. Este parece ser O(n), embora isso depende, naturalmente, como inteligente a implementação de ++SI.
O(n). No limite, conforme você muda tudo, deve ser O(n), embora você possa tentar adiar a criação da nova cópia para economizar tempo, ou dobrar seu tempo de acesso lendo changesets em vez do mapa original. O que tem melhor desempenho provavelmente depende do seu caso de uso.
Que tal usar 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#applycom um pouco mais clichê.
Começando Scala 2.13, por meio de construtores de fábrica aplicados com .to(factory):
Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")
Existe uma variante para criar um mutável vazio Mapque tem valores padrão retirados do imutável Map. Você pode armazenar um valor e substituir o padrão a qualquer momento:
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
Advertência (ver o comentário de Rex Kerr): Você não será capaz de remover os elementos vindos do mapa imutável:
scala> mMap.remove(1)
//res5: Option[String] = None
scala> mMap(1)
//res6: String = one