Search code examples
scalahashmapdefault-valuescala-collectionsmutable

Mutable HashMap with a mutable default value doesn't keep the changes


Suppose that I want a mutable HashMap[Int, HashSet[Int]] that has

  • integers as keys
  • mutable hash sets of integers as values

I want that an empty mutable HashSet is created by default whenever a value for a new key is accessed or updated.

Here is what I tried:

import collection.mutable.{HashMap, HashSet}

val hm = HashMap
  .empty[Int, HashSet[Int]]
  .withDefault(_ => HashSet.empty[Int])

hm(42) += 1234

println(hm)

The unexpected result is an empty HashMap. I expected a hash map with (42 -> HashSet(1234)) key-value pair.

Why doesn't the HashMap save the default mutable HashSets, and how do I fix this?


Solution

  • The statement

    hm(42) += 1234
    

    will create the default value (an empty HashSet), then update it by adding 1234 to it, then throw it away.


    If you want to update the HashMap itself, then remove the withDefault part from the definition, and use getOrElseUpdate instead:

    hm.getOrElseUpdate(42, HashSet.empty[Int]) += 1234
    

    Alternatively, you can leave the withDefault as-is, but update your hash map as follows:

    hm(42) = (hm(42) += 1234)