【问题标题】:Scala hashmap of listbuffers列表缓冲区的 Scala 哈希图
【发布时间】:2015-08-28 21:18:54
【问题描述】:

我正在尝试在 Scala 中模拟 defaultdict(list)(我已经声明了 scala.collection.mutable.HashMap)。

我现在正在尝试

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

然后要附加到列表中,我尝试如下:

d(integerKey) += integerValToInsertIntoList

但似乎没有任何效果,d 表现得好像它总是空的?

【问题讨论】:

  • 我想通了,我想,我做了val d= new HashMap[Int,ListBuffer[Int]](),然后在做追加时,我做了d.getOrElseUpdate(integerKey, new ListBuffer()) += integerValToInsertIntoList,但我不知道这是否是正确的方法,或者是否有更好的答案
  • 我怀疑d(integerKey) += integerValToInsertIntoListintegerKey 添加到d,所以每次它都会返回一个新的空ListBuffer
  • 好吧,我假设 d(integerkey) 指的是哈希图中的列表缓冲区,因此 += 将项目附加到缓冲区中,但我想我错了
  • 这似乎是一个很好的解决方案。
  • 我会让这个 q 保持打开状态,以防其他人有更好的答案/想要代表点

标签: list scala hashmap defaultdict


【解决方案1】:

这是为可变地图实现此功能的正确方法:

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)

注意

使用withDefaultValue 不能按预期对可变映射起作用。它将为所有新条目重用相同的“默认” ListBuffer()。

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

在 REPL 中,我们看到 d(4)(与 d(5) 相同)将包含两个新添加的条目:

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

【讨论】:

  • 为什么会这样? d(4) 总是相同的 ListBuffer。如果您检查,在d(5) append 44 之后,它将同时返回d(4)d(5)(甚至d(0)4, 5, 44。检查this fiddle
  • 很好,谢谢!我将它与不可变 Map 一起使用了很多次,我真的认为它也可以与可变 Map 一起按预期工作......似乎这个可变实现为所有新条目重用了相同的默认值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-21
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多