2011-02-18 17 views

Respuesta

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

¿Conoces la complejidad del tiempo asintótico de esto? Sé que Clojure puede convertir cualquiera de sus colecciones persistentes en una "transitoria" (es decir, una mutable con funciones de mutación de tipo lineal) y volver a una persistente en pasos 'O (1)'. Este * parece * ser 'O (n)', aunque eso depende por supuesto de cuán inteligente sea la implementación de '++'. –

+0

@ Jörg - Estoy bastante seguro de que este es 'O (n)'. En el límite a medida que cambia todo, debe ser 'O (n)', aunque podría intentar diferir la creación de la nueva copia para ahorrar tiempo o duplicar los tiempos de acceso leyendo los conjuntos de cambios en lugar del mapa original. Cuál funciona mejor depende probablemente de su caso de uso. –

+1

@Rustem: los mapas no están ordenados. Aparecerán en el orden que deseen (con un mapa hash, normalmente es el orden de la tecla hash). En particular, los mapas inmutables tienen casos especiales para mapas muy pequeños que son diferentes de los mapas mutables. –

3

¿Qué le parece 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) 
+0

* Es * genial, pero básicamente hace lo mismo que 'mutable.Map # apply' con un poco más repetitivo. –

0

Existe una variante para crear un vacío mutable Map que tiene valores por defecto tomados de la inmutable Map. Es posible almacenar un valor y reemplazar el valor predeterminado en cualquier 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 

Advertencia (ver el comentario de Rex Kerr): Usted no será capaz de eliminar los elementos que vienen del mapa inmutable:

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

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

Esto es útil en algunos casos, pero tenga en cuenta que no puede eliminar un elemento en su nuevo mapa que estaba presente en su mapa predeterminado; solo puede cubrir y descubrir los valores predeterminados. –

+0

Correcto, esta solución es parcial. –

92

La manera más limpia sería usar la fábrica mutable.Map varargs. A diferencia del enfoque ++, este utiliza el mecanismo CanBuildFrom, y por lo tanto tiene el potencial de ser más eficiente si el código de la biblioteca fue escrito para tomar ventaja de esto:

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

Esto funciona porque un Map también puede ser visto como una secuencia de pares.

+0

¿Puede explicarnos qué sintaxis usa en la segunda línea al pasar el parámetro? ¿Qué hace el colon? – Heinzi

+5

': _ *' es muy parecido a la adscripción de tipos, diciéndole al compilador exactamente qué tipo asignar a una expresión dada. Puede pensarlo aquí diciendo "tome esta secuencia y trátela como una serie de parámetros vararg". –

+12

Hay algo mal con las bibliotecas de colecciones si este es el más limpio;) – matanster

Cuestiones relacionadas