Update mutable HashMap value which is a mutable co

2020-04-11 13:17发布

问题:

I'm have a map that looks like this: Map[ A -> Collection[B]]. This map gets updated in a loop - the special thing is however, that updates mostly just mean adding an element B to the Collection[B] (for some key A).

I am trying to find out if I can get some speedup by changing the type of my Collection from List[ ] to ListBuffer[ ].

Up to now my code looked like this (simplified):

var incoming = new HashMap[A, List[B]() {
  override def default(a: A) = List()
}
..
for(b < someCollectionOfBs){
  ..
  incoming(b.getA) = b :: incoming(b.getA)
  ..
}

This works fine. Now, I changed the type of the map so it looks like this:

var incoming = new collection.mutable.HashMap[A, ListBuffer[B]() {
  override def default(a: A) = collection.mutable.ListBuffer()
}
..
for(b < someCollectionOfBs){
  ..
  incoming(b.getA) += b
  ..
}

Note the change in how the element B is added to the collection in the 2nd example (no more immutable List, hence we do not need to create and assign new collection...).

But. This does not work: incoming(X) += .. does not update the value of the map for X, actually it does not change anything.

What am I missing here? I thought that I should be able to update the values of a mutable HashMap... So, if my values are mutable collections, why can't I just add elements to those?

回答1:

The default is returned when the key is not found, but it does not update the map with the default value. You can use getOrElseUpdate for that.

incoming.getOrElseUpdate(b.getA, ListBuffer()) += b

That should do what you want.

Additional note:

If you're concerned about performance, I don't think replacing List with ListBuffer will buy you much, because you are prepending to a List and that should be very fast. ListBuffer is handy when you want to append to a list. You should look at using java.util.HashMap and see if that helps.