0

也许是一个简单的问题,但我没有从 API 中找到令人满意的答案。我不是想写好的代码,而是想更多地了解某些事情是如何工作的:

我创建了一个初始 HashMap。从任意列表中,我想使用 map 来创建 HashMaps 列表。我在 .map 函数中向我的 HashMap 添加了一个(键,值)对。因此,在此列表中的任何连续索引中,存储的 HashMap 的大小应该增加一(因此 list(i).size == list(i+1).size - 1 对于每个 i)。

但是通过以下代码剪辑,我得到了一个映射列表,它们都是相等的(即完整的 HashMap)。不过,如果我打印出不断增长的初始 HashMap 一切似乎都是正确的。

scala> import scala.collection.mutable.HashMap

val m = new HashMap[Int, Int]

List(1,2,3,4) map {e =>
    println(m)
    val newM = m += e -> (e+2)
    newM
}
Map()
Map(1 -> 3)
Map(1 -> 3, 2 -> 4)
Map(3 -> 5, 1 -> 3, 2 -> 4)

import scala.collection.mutable.HashMap
m: scala.collection.mutable.HashMap[Int,Int] = Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4)
res7: List[scala.collection.mutable.HashMap[Int,Int]] = List(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4),     Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4))

我所期望的是

列表(地图(1 -> 2),地图(1 -> 2, 2 -> 4),地图(1 -> 2, 2 -> 4, 3 -> 5),地图(1 -> 2, 2 - > 4, 3 -> 5, 4 -> 6))

使用生成 for 循环的等效(我假设是)版本会产生完全相同的结果:

scala> for {
    i <- 1 to 4
    val newM = m += i -> (i+2)
} yield newM
 res10: scala.collection.immutable.IndexedSeq[scala.collection.mutable.HashMap[Int,Int]] = Vector(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4))

scala> for (i <- 1 to 4) yield {
    val newM = m += i -> (i+2)
    println(m)
    newM
} 
Map(1 -> 3)
Map(1 -> 3, 2 -> 4)
Map(3 -> 5, 1 -> 3, 2 -> 4)
Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4)
res11: scala.collection.immutable.IndexedSeq[scala.collection.mutable.HashMap[Int,Int]] = Vector(Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4), Map(3 -> 5, 4 -> 6, 1 -> 3, 2 -> 4))

我想我错过了一个基本步骤,但我只是看不出是哪个。我感谢任何进一步的帮助!

随后的问题:显然,(键,值)对的打印顺序总是相同的(尽管不是按照它们是元素的顺序,但我不希望 Map 无论如何,这是自然的)。当存储对时,后台会发生什么情况似乎总是如此?

4

1 回答 1

4

m是一个可变的 HashMap。

+=方法将一个新元素添加到同一张地图,并返回该地图。

您已为地图命名newM,但这是一条红鲱鱼!这只是同一张地图m。所以他们都只是m

如果你真的想要一份副本,你可以打电话clonem例如val newM = (m += e -> (e+2)).clone)。

或者,如果您想随时构建一个不可变的地图,您可以使用以下scan方法:

List(1,2,3,4).scanLeft(collection.immutable.HashMap[Int,Int]()){ (m,e) => m + (e -> (e+2)) }

它需要一个项目(在这种情况下是一个空地图)并逐步构建它,完成后将整个历史记录返回给您:

res7: List[scala.collection.immutable.HashMap[Int,Int]]
  = List(Map(), Map(1 -> 3), Map(1 -> 3, 2 -> 4),
         Map(1 -> 3, 2 -> 4, 3 -> 5), Map(1 -> 3, 2 -> 4, 3 -> 5, 4 -> 6))

更好的是,你可以

List(1,2,3,4).map(e => e -> (e+2)).toMap

无需担心构建过程即可获得最终地图。

于 2012-04-04T22:10:27.820 回答