Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map withDefault of an empty ListBuffer in scala

Tags:

map

scala

mutable

I'm trying to create a mutable Map with a default that creates a new ListBuffer when an element is requested that is not already in the map. However, while the new map is returned as the default it does not remain in the map. Maybe this is just how it works, I thought, but when I tested it with an Int rather than a ListBuffer it did exactly as I wanted. Here's some code to explain what I mean - what am I doing wrong?

First, here it is working with a Map[Int]:

scala> val a = collection.mutable.Map(1 -> 1).withDefault(i => 0)
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 1)

scala> a(1) += 1 // adding to an existing element works as expected

scala> a
res48: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> a(2) += 1 // what about adding to a non-existing element?

scala> a // the new element has been added to the map
res50: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2, 2 -> 1)

Now with a Map[ListBuffer[Int]]:

scala> val b = collection.mutable.Map(1 -> collection.mutable.ListBuffer[Int]()).withDefault(i => collection.mutable.ListBuffer.empty[Int])
b: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer())

scala> b(1) += 1 // appending to an existing element works as expected
res51: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala> b
res52: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1))

scala> b(2) += 1 // but appending to a non-existing element...
res53: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1)

scala> b // leaves the map unchanged
res54: scala.collection.mutable.Map[Int,scala.collection.mutable.ListBuffer[Int]] = Map(1 -> ListBuffer(1))
like image 875
Russell Avatar asked Oct 08 '22 08:10

Russell


1 Answers

The difference is this:

In the first case a(2) is an Int. Since Int doesn't have a += method, a(2) += 1 is equivalent a(2) = a(2) + 1 and so to a.update(2, a(2) + 1). The update actually changes the map.

But ListBuffer[Int] does have a += method, so your call is a(2).+=(1), and you don't set a(2) to anything!

like image 86
Alexey Romanov Avatar answered Oct 13 '22 11:10

Alexey Romanov