Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Scala中预编LinkedHashMap的变通方法?_Scala_Immutability_Linkedhashmap - Fatal编程技术网

在Scala中预编LinkedHashMap的变通方法?

在Scala中预编LinkedHashMap的变通方法?,scala,immutability,linkedhashmap,Scala,Immutability,Linkedhashmap,我有一个LinkedHashMap,我一直以一种典型的方式使用它:添加新的键值 配对,并按插入顺序访问它们。但是,现在我有一个 特殊情况下,我需要向地图的“头部”添加对。我想有 LinkedHashMap源代码中的一些功能用于执行此操作,但它具有私有 可访问性 我有一个解决方案,创建一个新映射,添加映射对,然后添加所有旧映射。 在Java语法中: newMap.put(newKey, newValue) newMap.putAll(this.map) this.map = newMap 它起

我有一个LinkedHashMap,我一直以一种典型的方式使用它:添加新的键值 配对,并按插入顺序访问它们。但是,现在我有一个 特殊情况下,我需要向地图的“头部”添加对。我想有 LinkedHashMap源代码中的一些功能用于执行此操作,但它具有私有 可访问性

我有一个解决方案,创建一个新映射,添加映射对,然后添加所有旧映射。 在Java语法中:

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)