How can I convert immutable.Map
to mutable.Map
in Scala so I can update the values in Map
?

- 38,521
- 31
- 149
- 235

- 48,526
- 41
- 139
- 208
6 Answers
The cleanest way would be to use the mutable.Map
varargs factory. Unlike the ++
approach, this uses the CanBuildFrom
mechanism, and so has the potential to be more efficient if library code was written to take advantage of this:
val m = collection.immutable.Map(1->"one",2->"Two")
val n = collection.mutable.Map(m.toSeq: _*)
This works because a Map
can also be viewed as a sequence of Pairs.

- 49,540
- 9
- 105
- 155
-
2Can you explain, what syntax you use in the second line when passing the parameter? What does the colon do? – Heinzi Jun 01 '12 at 15:29
-
7`: _*` is much like type ascription, telling the compiler exactly what type to asign to a given expression. You can think of it here as saying "take this sequence, and treat it as a number of vararg params." – Kevin Wright Jun 06 '12 at 10:58
-
19There's something wrong with the collection libraries if this is the cleanest ;) – matanster Nov 08 '15 at 20:57
-
2@matt It could be made a bit shorter with aliased imports, but bear in mind that sacrificing immutability is *very* non-idiomatic for Scala, not exactly the sort of thing I'd enourage by making it look even easier... Out of curiosity, how else could you propose doing it more cleanly, if not via a copy? – Kevin Wright Nov 08 '15 at 21:08
-
That is my point, I can't, but a better collections library could make this possible, IMHO. – matanster Nov 08 '15 at 21:12
-
@Kevin Wright it would be cleaner if the mutable map supported construction from immutable map types eg. ```val m = collection.immutable.Map(1->"one",2->"Two")``` ```val n = collection.mutable.Map(m)``` – Tez Sep 09 '22 at 00:27
val myImmutableMap = collection.immutable.Map(1->"one",2->"two")
val myMutableMap = collection.mutable.Map() ++ myImmutableMap

- 166,841
- 26
- 322
- 407
-
1Do you know hat the asymptotic time complexity of this is? I know that Clojure can turn any of its persistent collections into a "transient" one (i.e. a mutable one with linearly-typed mutation functions) and back into a persistent one in `O(1)` steps. This *looks* to be `O(n)`, although that depends of course on how clever the implementation of `++` is. – Jörg W Mittag Feb 18 '11 at 15:34
-
1@Jörg - I'm pretty sure this one is `O(n)`. In the limit as you change everything, it must be `O(n)`, though you could try to defer the creation of the new copy to save time, or you double your access times by reading changesets instead of the original map. Which one performs best probably depends on your use case. – Rex Kerr Feb 18 '11 at 16:00
-
1@Rustem - Maps are unordered. They'll appear in whichever order they feel like (with a hash map, it's typically the order of the hash key). In particular, immutable maps have special cases for really tiny maps which are different from mutable maps. – Rex Kerr Feb 18 '11 at 16:47
-
Starting Scala 2.13
, via factory builders applied with .to(factory)
:
Map(1 -> "a", 2 -> "b").to(collection.mutable.Map)
// collection.mutable.Map[Int,String] = HashMap(1 -> "a", 2 -> "b")

- 54,987
- 21
- 291
- 190
How about using 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)

- 1,145
- 7
- 7
-
It *is* cool, but basically does the same thing as `mutable.Map#apply` with a bit more boilerplate. – Kevin Wright Feb 20 '11 at 01:19
There is a variant to create an empty mutable Map
that has default values taken from the immutable Map
. You may store a value and override the default at any time:
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
Caveat (see the comment by Rex Kerr): You will not be able to remove the elements coming from the immutable map:
scala> mMap.remove(1)
//res5: Option[String] = None
scala> mMap(1)
//res6: String = one

- 12,971
- 2
- 50
- 54
-
3This is useful in some cases, but note that you are unable to remove an element in your new map that was present in your default map; you can only cover and uncover the defaults. – Rex Kerr Feb 18 '11 at 20:30
-
With scala 2.13, there are two alternatives: the to
method of the source map instance, or the from
method of the destination map's companion object.
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)
As you can see, the mutable.Map
implementation was decided by the library.
If you want to choose a particular implementation, for example mutable.HashMap
, replace all occurrences of mutable.Map
with mutable.HashMap
.

- 994
- 1
- 10
- 18