Why does my Map claim to have no keys after adding

2019-09-21 08:47发布

问题:

I have a map of Int->Queue, and I'm adding to the queues one entry at a time. At the end of the process I need to iterate over the keys and values (because I want to convert the Queues to Arrays), but scala says there are no keys/values in the map. Some simplified code below for illustration purposes. What is going on here? The result of m(4) below is also puzzling.

import scala.collection.mutable.Queue

val m = Map[Int, Queue[Int]]().withDefaultValue(Queue[Int]())

m(1) += 10
res25: scala.collection.mutable.Queue[Int] = Queue(10)

m(1) += 10
res26: scala.collection.mutable.Queue[Int] = Queue(10, 10)

m(1)
res35: scala.collection.mutable.Queue[Int] = Queue(10, 10)

m(4)
res37: scala.collection.mutable.Queue[Int] = Queue(10, 10)

m.keys
res28: Iterable[Int] = Set()

m
res36: scala.collection.immutable.Map[Int,scala.collection.mutable.Queue[Int]] = Map()

Using scala 2.10.3.

回答1:

You never add anything to the map. You are getting the mutable queue that you set as the default value and modifying that.



回答2:

Yes, you do have to check if the Queue at a given index has been created or not, but the syntax need not be quite so "laborious."

import scala.collection.mutable.Queue
val mutablemap = scala.collection.mutable.Map[Int, Queue[Int]]()

mutablemap(9) = mutablemap.lift(9).fold(Queue(99))(_ += 99)
mutablemap(2) = mutablemap.lift(2).fold(Queue(22))(_ += 22)
mutablemap(9) = mutablemap.lift(9).fold(Queue(19))(_ += 19)
mutablemap(2) = mutablemap.lift(2).fold(Queue(12))(_ += 12)

mutablemap(9)  // res0: scala.collection.mutable.Queue[Int] = Queue(99, 19)
mutablemap(2)  // res1: scala.collection.mutable.Queue[Int] = Queue(22, 12)

update

On further reflection, your original design wasn't too far off the mark.

import scala.collection.mutable.Queue
val mutablemap = 
  scala.collection.mutable.Map[Int, Queue[Int]]().withDefault(_ => Queue[Int]())

mutablemap(3) = mutablemap(3) += 37
mutablemap(3) = mutablemap(3) += 45
mutablemap(6) = mutablemap(6) += 60
mutablemap(6) = mutablemap(6) += 62

mutablemap(3)  // res0: scala.collection.mutable.Queue[Int] = Queue(37, 45)
mutablemap(6)  // res1: scala.collection.mutable.Queue[Int] = Queue(60, 62)


回答3:

Leveraging puhlen's answer:

First, I need to switch to a mutable map. Second, the use of withDefaultValue seems to be irrelevant to this problem (which is counterintuitive).

val mutablemap = scala.collection.mutable.Map[Int, Queue[Int]]()

When adding key-value pairs to the map, I have to laboriously check to see if the key exists first (because I don't want to destroy any pre-existing key-value pair, because I'm incrementally building up the queues):

if (mutablemap.contains(key)) {
    // mutate the existing Queue
    mutablemap(key) += new_value
} else {
    // key was not in map; start a new Queue
    mutablemap += key -> Queue[Int](first_value)
}


标签: scala