你看了一下LinkedHashMap的代碼嗎?該班有一個firstEntry
字段,只需快速瀏覽updateLinkedEntries
,創建LinkedHashMap
的子類應該相對容易,該子類只會添加新方法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
}
}
}
測試是這樣的:
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 ));
}
}
其中,在斯卡拉2.9.0(是的,需要更新)結果
x:olol y: 12
x:bar y: 6
x:foo y: 5
快速基準顯示之間的性能差異量級擴展內置類和「地圖重寫」的做法(我使用Debilski在「ExternalMethod」答案的代碼和我在「內建」 ):
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
}
}
使用scala benchmarking template。
這是一個讓我把核心數據結構保持爲val而不是var的手段。我又走了一步,並使用Scala的「隱式def」特性對LinkedHashMap進行了臨時擴展(添加了prepend())。 – 2012-07-10 22:11:53