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 ));
}
}
これは、Scala 2.9.0 (ええ、更新する必要があります) では、
x:olol y: 12
x:bar y: 6
x:foo y: 5
簡単なベンチマークは、拡張された組み込みクラスと「マップ書き換え」アプローチの間のパフォーマンスの違いの桁違いを示しています(「ExternalMethod」でDebilskiの回答のコードを使用し、「BuiltIn」で私のコードを使用しました):
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 ベンチマーク テンプレートの使用。