As other have stated here, the method you might be looking for is called mapValues
:
val myMap = Map("one" -> 1, "two" -> 2)
val newMap = myMap.mapValues(_ + 1)
println(newMap) //Map(one -> 2, two -> 3)
But you have to be very careful with that method, since its underlying implementation is a view, meaning it is lazily evaluated. Since most of the other methods on immutable.Map
do not behave similarly, this can be surprising, confusing, or lead to bugs. For example:
val it = Iterator.from(0)
val myMap = Map("one" -> 1, "two" -> 2)
val newMap = myMap.mapValues(_ + it.next)
println(newMap) //Map(one -> 3, two -> 5), as expected
//Try printing again, though:
println(newMap) //Map(one -> 5, two -> 7), I thought this map was immutable!
So the values in newMap
are reevaluated each time the map is iterated! This is done as an optimization by delaying evaluation of the map and avoiding iteration when possible. This might be counter-intuitive, and this method even has several other questions and blog posts dedicated to it because of issues related to this confusion, worth reading if you are interested in using this method.
One way to gain a stable mapping while using the concise mapValues
syntax is to force
the underlying view
implementation of the map:
val newMap = myMap.mapValues(_ + it.next).view.force //now stable!
You can also call toSeq
and then toMap
, but this has performance implications.
At then end of the day, it might be simpler to just use a regular map
or a for
comprehension:
//If you prefer "map":
myMap.map { case (key, value) => (key, value + 1) }
//If you prefer "for"
for { (key, value) <- map } yield (key, value + 1)