有没有一种优雅的方式可以更新Map中已经存在的值?
这看起来太可怕了:
val a = map.get ( something )
if ( a != null ) // case .. excuse my old language
a.apply( updateFunction )
else
map.put ( something, default )
有没有一种优雅的方式可以更新Map中已经存在的值?
这看起来太可怕了:
val a = map.get ( something )
if ( a != null ) // case .. excuse my old language
a.apply( updateFunction )
else
map.put ( something, default )
大多数情况下,您可以插入一些可以在创建时更新的内容(例如,如果它是计数,则将0放入其中,然后更新为1,而不仅仅是将1放入开始)。 在这种情况下,
map.getOrElseUpdate(something, default).apply(updateFunction)
在极少数情况下,如果您无法以这种方式组织事物,
map(something) = map.get(something).map(updateFunction).getOrElse(default)
(但你必须两次引用something
。)
这是我通常写的东西......不确定是否有更好的解决方案。
map.get(key) match {
case None => map.put(key, defaultValue)
case Some(v) => map(key) = updatedValue
}
update
和put
是相同的,但我通常在现有条目上使用update
,而在新条目上使用put
,只是为了可读性。map(key) = value
,它会自动创建/替换条目。map(key) += 1
这样的语句实际上在Map
中起作用(这通常适用于具有update
函数的集合),许多简单的数字操作也是如此。
class ValueStore(var value: ValueType)
val map = new Map[KeyType, ValueStore]
...
map.get(key) match {
case None => map.put(key, new ValueStore(defaultValue))
case Some(v) => v.value = updatedValue
}
HashMap
的底层结构是 HashTable
,它实际上采用了可变包装类的方法。尽管 HashMap
是一个更好的包装类,但有时你仍需要进行重复计算。请保留 HTML 标记。get
上,一次在put
或apply上。 - Rex KerrHashMap
已经被优化得很好了,所以键访问几乎是常数时间,所以你不需要太担心它。2.另一个可能性是,使你的value
成为可变对象。而不是将新值替换到其中,你只需获取该值对象并对其进行修改。这意味着在创建条目(key,value)之后,您永远不必再次调用put
。但我想这种方法有点违反正确使用Map
的方式。 - KaneHashMap
的实现,你会发现底层数据结构实际上是HashTable
,而HashTable
正是使用了这种可变的方法来实现。HashMap
可以被看作是对HashTable
的一个很好的封装,提供了许多方便的功能,只是有时候你需要进行一些虚拟操作。 - Kane我很蠢,你是(相当)正确的:
map.get(key) match {
case None => map.put(key, defaultValue)
case Some(v) => v.apply(updateFunction) // changes state of value
}
测试 谢谢
getOrElseUpdate
目前的实现方式也是双重查找,但至少它有潜力通过库更新进行优化(对于可以在添加时更新的情况),也许在 2.11 版本中会针对性能进行优化。 - Rex Kerrmap.changeValue(key, f)
,那么没有这样的方法。如果你的值是可变的,那么我上面写的代码将起作用。 - Rex Kerr