Jak mogę przekonwertować immutable.Map
na mutable.Map
w Scali, aby zaktualizować wartości w Map
?
scala
dictionary
scala-2.8
Łukasz Lew
źródło
źródło
: _*
jest bardzo podobny do przypisywania typów, mówiąc kompilatorowi dokładnie, jaki typ przypisać do danego wyrażenia. Możesz myśleć o tym tutaj jako o powiedzeniu „weź tę sekwencję i potraktuj ją jako kilka parametrów vararg”.val myImmutableMap = collection.immutable.Map(1->"one",2->"two") val myMutableMap = collection.mutable.Map() ++ myImmutableMap
źródło
O(1)
stopniowo z powrotem w trwałą . To wygląda sięO(n)
, mimo że zależy oczywiście od tego jak sprytny realizacji++
JEST.O(n)
. W granicach możliwości zmiany wszystkiego musi byćO(n)
, chociaż możesz spróbować odłożyć tworzenie nowej kopii, aby zaoszczędzić czas, lub podwoić czas dostępu, czytając zestawy zmian zamiast oryginalnej mapy. To, który z nich działa najlepiej, zależy prawdopodobnie od twojego przypadku użycia.Począwszy od
Scala 2.13
konstruktorów fabryk zastosowanych w.to(factory)
:Map(1 -> "a", 2 -> "b").to(collection.mutable.Map) // collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")
źródło
A co powiesz na używanie 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)
źródło
mutable.Map#apply
z nieco bardziej szablonowe.Istnieje wariant tworzenia pustej mutacji,
Map
która ma wartości domyślne pobrane z niezmiennejMap
. W dowolnym momencie możesz zapisać wartość i zastąpić wartość domyślną: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
Uwaga (patrz komentarz Rexa Kerra): Nie będziesz w stanie usunąć elementów pochodzących z niezmiennej mapy:
scala> mMap.remove(1) //res5: Option[String] = None scala> mMap(1) //res6: String = one
źródło
W scali 2.13 istnieją dwie alternatywy:
to
metoda instancji mapy źródłowej lubfrom
metoda obiektu towarzyszącego mapy docelowej.scala> import scala.collection.mutable import scala.collection.mutable scala> val immutable = Map(1 -> 'a', 2 -> 'b'); val immutable: scala.collection.immutable.Map[Int,Char] = Map(1 -> a, 2 -> b) scala> val mutableMap1 = mutable.Map.from(immutable) val mutableMap1: scala.collection.mutable.Map[Int,Char] = HashMap(1 -> a, 2 -> b) scala> val mutableMap2 = immutable.to(mutable.Map) val mutableMap2: scala.collection.mutable.Map[Int,Char] = HashMap(1 -> a, 2 -> b)
Jak widać, o
mutable.Map
wdrożeniu zadecydowała biblioteka. Jeśli chcesz wybrać konkretną implementację, na przykładmutable.HashMap
, zastąpić wszystkie wystąpieniamutable.Map
zmutable.HashMap
.źródło