Is there an elegant way in to update an already existing value in a Map?
This looks too scary:
val a = map.get ( something )
if ( a != null ) // case .. excuse my old language
a.apply( updateFunction )
else
map.put ( something, default )
Most of the time you can insert something that can be updated when it's created (e.g. if it's a count, you put 0 in it and then update to 1 instead of just putting 1 in to start). In that case,
map.getOrElseUpdate(something, default).apply(updateFunction)
In the rare cases where you can't organize things this way,
map(something) = map.get(something).map(updateFunction).getOrElse(default)
(but you have to refer to something twice).
This is what I usually write... not sure if there are better solutions.
map.get(key) match {
case None => map.put(key, defaultValue)
case Some(v) => map(key) = updatedValue
}
In fact update and put are the same for mutable map, but I usually use update on existing entries and put for new ones, just for readability.
Another thing is that if you can figure out what the ultimate value is without checking the existence of the key, you can simply write map(key) = value, at it automatically creates/replaces the entry.
Finally, statements like map(key) += 1 actually works in Map (this is generally true for collections with update function), and so do many simple numeric operations.\
To solve double put, use mutable object instead of immutable values:
class ValueStore(var value: ValueType)
val map = new Map[KeyType, ValueStore]
...
map.get(key) match {
case None => map.put(key, new ValueStore(defaultValue))
case Some(v) => v.value = updatedValue
}
As I mentioned in the comment, the underlying structure of HashMap is HashTable, which actually use this mutable wrapper class approach. HashMap is a nicer wrap-up class but you sometimes just have to do duplicated computation.
me stupid, you are (quite) right:
map.get(key) match {
case None => map.put(key, defaultValue)
case Some(v) => v.apply(updateFunction) // changes state of value
}
tsts thanks