我有一个LinkedHashMap,我一直在以一种典型的方式使用:添加新的键值 成对结束,并按插入顺序访问它们。但是,现在我有了 特殊情况,我需要将对添加到地图的“头部”。我觉得有 LinkedHashMap源中的一些功能用于执行此操作,但它具有私有功能 可访问性。
我有一个解决方案,我在其中创建一个新地图,添加该对,然后添加所有旧映射。 在Java语法中:
newMap.put(newKey, newValue)
newMap.putAll(this.map)
this.map = newMap
有效。但问题是我需要建立我的主要数据结构 (this.map)一个var而不是一个val。
有人能想到更好的解决方案吗?请注意,我肯定需要快速查找 Map集合提供的功能。预先支出的表现不是 这么大的一笔。
更一般地说,作为一名Scala开发人员,你会为了避免变数而努力 在这样的情况下,假设没有可预见的并发需求? 你会创建自己的LinkedHashMap版本吗?坦白地说,看起来很麻烦。
答案 0 :(得分:1)
您是否看过LinkedHashMap的代码?该类有一个字段firstEntry
,只需快速查看updateLinkedEntries
,创建LinkedHashMap
的子类就相对容易了,它只添加一个新方法{{1} }和prepend
导致您需要的行为,例如(未经测试):
updateLinkedEntriesPrepend
这是一个示例实现我快速拼凑(即未经过全面测试!):
private def updateLinkedEntriesPrepend(e: Entry) {
if (firstEntry == null) { firstEntry = e; lastEntry = e }
else {
val oldFirstEntry = firstEntry
firstEntry = e
firstEntry.later = oldFirstEntry
oldFirstEntry.earlier = e
}
}
像这样测试:
class MyLinkedHashMap[A, B] extends LinkedHashMap[A,B] {
def prepend(key: A, value: B): Option[B] = {
val e = findEntry(key)
if (e == null) {
val e = new Entry(key, value)
addEntry(e)
updateLinkedEntriesPrepend(e)
None
} else {
// The key already exists, so we might as well call LinkedHashMap#put
put(key, value)
}
}
private def updateLinkedEntriesPrepend(e: Entry) {
if (firstEntry == null) { firstEntry = e; lastEntry = e }
else {
val oldFirstEntry = firstEntry
firstEntry = e
firstEntry.later = oldFirstEntry
oldFirstEntry.earlier = firstEntry
}
}
}
其中,在Scala 2.9.0上(是的,需要更新)结果
object Main {
def main(args:Array[String]) {
val x = new MyLinkedHashMap[String, Int]();
x.prepend("foo", 5)
x.prepend("bar", 6)
x.prepend("olol", 12)
x.foreach(x => println("x:" + x._1 + " y: " + x._2 ));
}
}
快速基准测试显示扩展内置类和“地图重写”方法之间性能差异的数量级(我使用Debilski在“ExternalMethod”中的答案和我在“BuiltIn”中的答案):
x:olol y: 12
x:bar y: 6
x:foo y: 5
基准代码:
benchmark length us linear runtime
ExternalMethod 10 1218.44 =
ExternalMethod 100 1250.28 =
ExternalMethod 1000 19453.59 =
ExternalMethod 10000 349297.25 ==============================
BuiltIn 10 3.10 =
BuiltIn 100 2.48 =
BuiltIn 1000 2.38 =
BuiltIn 10000 3.28 =
答案 1 :(得分:1)
这可行,但也不是特别好:
import scala.collection.mutable.LinkedHashMap
def prepend[K,V](map: LinkedHashMap[K,V], kv: (K, V)) = {
val copy = map.toMap
map.clear
map += kv
map ++= copy
}
val map = LinkedHashMap('b -> 2)
prepend(map, 'a -> 1)
map == LinkedHashMap('a -> 1, 'b -> 2)