Wie kann ich in Scala konvertieren immutable.Map
, mutable.Map
um die Werte in zu aktualisieren Map
?
Wie kann ich in Scala konvertieren immutable.Map
, mutable.Map
um die Werte in zu aktualisieren Map
?
Antworten:
Am saubersten wäre es, die mutable.Map
Varargs-Fabrik zu benutzen . Im Gegensatz zum ++
Ansatz verwendet dies den CanBuildFrom
Mechanismus und kann daher effizienter sein, wenn Bibliothekscode geschrieben wurde, um dies auszunutzen:
val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*)
Dies funktioniert, weil a Map
auch als Folge von Paaren angesehen werden kann.
: _*
ähnelt der Typzuweisung und teilt dem Compiler genau mit, welcher Typ einem bestimmten Ausdruck zugewiesen werden soll. Sie können sich das hier so vorstellen, dass Sie sagen: "Nehmen Sie diese Sequenz und behandeln Sie sie als eine Reihe von vararg-Parametern."
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap
O(1)
. Dies scheint zu sein O(n)
, obwohl dies natürlich davon abhängt, wie clever die Implementierung ++
ist.
O(n)
. Wenn Sie alles ändern, muss dies der Fall sein O(n)
. Sie können jedoch versuchen, die Erstellung der neuen Kopie zu verschieben, um Zeit zu sparen, oder Sie verdoppeln Ihre Zugriffszeiten, indem Sie Änderungssätze anstelle der ursprünglichen Karte lesen. Welche Leistung am besten erbracht wird, hängt wahrscheinlich von Ihrem Anwendungsfall ab.
Wie wäre es mit 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#apply
mit etwas mehr Boilerplate.
Starten Scala 2.13
über Fabrikbauer angewendet mit .to(factory)
:
Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")
Es gibt eine Variante, um eine leere veränderbare Variable zu erstellen Map
, deren Standardwerte von der unveränderlichen übernommen wurden Map
. Sie können jederzeit einen Wert speichern und den Standardwert überschreiben:
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
Vorsichtsmaßnahme (siehe Kommentar von Rex Kerr): Sie können die Elemente aus der unveränderlichen Karte nicht entfernen:
scala> mMap.remove(1)
//res5: Option[String] = None
scala> mMap(1)
//res6: String = one