Scala hashmap of listbuffers

509 Views Asked by At

I am trying to emulate a defaultdict(list) in Scala (I've already declared scala.collection.mutable.HashMap).

Right now I am trying

val d = new HashMap[Int,ListBuffer[Int]](){ override def default(key:Int) = ListBuffer[Int]() }

And then to append to a list I try something like:

d(integerKey) += integerValToInsertIntoList

But nothing seems to work and d acts like it's always empty?

1

There are 1 best solutions below

2
On

Here is the proper way of implementing this for mutable Maps:

val d = new HashMap[Int,ListBuffer[Int]]() {
   override def apply(key: Int) = super.getOrElseUpdate(key, ListBuffer())
}
d(4) append 4
d(5) append 5
scala> d(4)
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4)
scala> d(5)
res2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(5)

Note

Using withDefaultValue does not work as expected for mutable Maps. It will reuse the same "default" ListBuffer() for all new entries.

val d = new HashMap[Int,ListBuffer[Int]]().withDefaultValue(ListBuffer())
d(4) append 4
d(5) append 5

In the REPL we see that d(4) (same for d(5)) will hold both new added entries:

scala> d(4)
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4, 5)
scala> d(5)
res2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4, 5)