2011-12-26 64 views
1

我有一个如下所示的地图:Map[ A -> Collection[B]]。这个映射在一个循环中得到更新 - 但是特别的是,更新大多只是意味着向集合[B](对于某个关键字A)添加一个元素B.更新可变HashMap值,这是一个可变集合

我想知道我是否可以通过将列表[]的类型更改为ListBuffer []来获得一些加速。

截至目前我的代码看起来像这样(简化):

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

这工作得很好。现在,我改变了地图的类型,所以它看起来是这样的:

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

注意在B元素是如何加入到集合中的第二个例子(没有更多的不可变List的变化,因此我们不需要创建并分配新的集合...)。

但是。这不起作用:incoming(X) += ..确实不是更新X的地图的值,实际上它不会改变任何东西。

我在这里错过了什么?我认为我应该能够更新可变HashMap的值...所以,如果我的值是可变集合,为什么我不能只添加元素给那些?

回答

6

找不到密钥时会返回默认值,但不会使用默认值更新地图。你可以使用getOrElseUpdate

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

这应该做你想做的。

附加说明:

如果你关心性能,我不认为有ListBuffer更换List会买你多少,因为你前面加上一个List这应该是非常快的。当你想追加到列表时,ListBuffer很方便。你应该看看使用java.util.HashMap,看看是否有帮助。

+0

啊,这是一个邪恶的小动作。 :) 谢谢。 – fgysin 2011-12-27 10:51:44

+0

关于性能:构建列表并不是我担心的事情,而是实际创建新的List实例。此外,在我的代码垃圾收集完成率是一个问题,创造更少的对象应该肯定帮助我在那里... – fgysin 2011-12-27 10:53:51