Scala: Why mapValues produces a view and is there any stable alternatives?
The scala doc say:
a map view which maps every
key
of this map tof(this(key))
. The resulting map wraps the original map without copying any elements.
So this should be expected, but this scares me a lot, I'll have to review bunch of code tomorrow. I wasn't expecting a behavior like that :-(
Just an other workaround:
You can call toSeq
to get a copy, and if you need it back to map toMap
, but this unnecessary create objects, and have a performance implication over using map
One can relatively easy write, a mapValues
which doesn't create a view, I'll do it tomorrow and post the code here if no one do it before me ;)
EDIT:
I found an easy way to 'force' the view, use '.map(identity)' after mapValues (so no need of implementing a specific function):
scala> val xs = Map("a" -> 1, "b" -> 2)
xs: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1, b -> 2)
scala> val ys = xs.mapValues(_ + Random.nextInt).map(identity)
ys: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1315230132, b -> 1614948101)
scala> ys
res7: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 1315230132, b -> 1614948101)
It's a shame the type returned isn't actually a view! othewise one would have been able to call 'force' ...
There's a ticket about this, SI-4776 (by YT).
The commit that introduces it has this to say:
Following a suggestion of jrudolph, made
filterKeys
andmapValues
transform abstract maps, and duplicated functionality for immutable maps. Movedtransform
andfilterNot
from immutable to general maps. Review by phaller.
I have not been able to find the original suggestion by jrudolph, but I assume it was done to make mapValues
more efficient. Give the question, that may come as a surprise, but mapValues
is more efficient if you are not likely to iterate over the values more than once.
As a work-around, one can do mapValues(...).view.force
to produce a new Map
.