在Scala中预编LinkedHashMap的变通方法?
我有一个LinkedHashMap,我一直以一种典型的方式使用它:添加新的键值 配对,并按插入顺序访问它们。但是,现在我有一个 特殊情况下,我需要向地图的“头部”添加对。我想有 LinkedHashMap源代码中的一些功能用于执行此操作,但它具有私有 可访问性 我有一个解决方案,创建一个新映射,添加映射对,然后添加所有旧映射。 在Java语法中:在Scala中预编LinkedHashMap的变通方法?,scala,immutability,linkedhashmap,Scala,Immutability,Linkedhashmap,我有一个LinkedHashMap,我一直以一种典型的方式使用它:添加新的键值 配对,并按插入顺序访问它们。但是,现在我有一个 特殊情况下,我需要向地图的“头部”添加对。我想有 LinkedHashMap源代码中的一些功能用于执行此操作,但它具有私有 可访问性 我有一个解决方案,创建一个新映射,添加映射对,然后添加所有旧映射。 在Java语法中: newMap.put(newKey, newValue) newMap.putAll(this.map) this.map = newMap 它起
newMap.put(newKey, newValue)
newMap.putAll(this.map)
this.map = newMap
它起作用了。但这里的问题是,我需要创建我的主数据结构
(this.map)var而不是val
有人能想出更好的解决办法吗?请注意,我确实需要快速查找
地图集合提供的功能。预结尾的性能不是很好
这么大的一件事
更一般地说,作为一名Scala开发人员,您将如何努力避免var
在这种情况下,假设没有可预见的并发需求?
你会创建自己版本的LinkedHashMap吗?坦率地说,这看起来很麻烦。你看了密码了吗?该类有一个字段
firstEntry
,只需快速浏览一下updateLinkedEntries
,就可以相对容易地创建LinkedHashMap
的子类,该子类只添加一个新方法prepend
和updateLinkedEntriesPrepend
,从而产生所需的行为,例如(未测试):
下面是一个示例实现,我很快就完成了(也就是说,没有经过彻底测试!): 测试如下:
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 ));
}
}
在Scala 2.9.0上(是的,需要更新)会导致
x:olol y: 12
x:bar y: 6
x:foo y: 5
快速基准测试显示了扩展内置类和“映射重写”方法之间性能差异的数量级(我在“ExternalMethod”中使用了Debilski的答案代码,在“BuiltIn”中使用了我的答案代码): 基准代码:
def timeExternalMethod(reps: Int) = {
var r = reps
while(r > 0) {
for(i <- 1 to 100) prepend(map, (i, i))
r -= 1
}
}
def timeBuiltIn(reps: Int) = {
var r = reps
while(r > 0) {
for(i <- 1 to 100) map.prepend(i, i)
r -= 1
}
}
def timeExternalMethod(reps:Int)={
var r=重复次数
而(r>0){
对于(i 0){
对于(i这将起作用,但也不是特别好:
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)
这是一个花招,使我能够将我的核心数据结构保留为val而不是var。我更进一步,使用“隐式定义”对LinkedHashMap进行了特别扩展(添加prepend())Scala的特性。这会起作用,但我想避免扩展内置类和维护这样的新类型。另一方面,使用“隐式定义”的快速本地扩展(请参阅对前面答案的注释)似乎更容易接受。虽然我理解您希望保持简单,但我不同意使用隐式实际上比扩展LinkedHashMap更简单。如果您需要此功能(即,在LinkedHashMap中预先添加)如果正确实现,它甚至可能会被提交到标准库中。但是,当我总是重写整个映射时,我主要关心的是性能,如我的答案编辑部分所示。
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 =
def timeExternalMethod(reps: Int) = {
var r = reps
while(r > 0) {
for(i <- 1 to 100) prepend(map, (i, i))
r -= 1
}
}
def timeBuiltIn(reps: Int) = {
var r = reps
while(r > 0) {
for(i <- 1 to 100) map.prepend(i, i)
r -= 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)