このようなデータ構造は、安全ではないため、私の知る限り存在しません。特定の状態を確実にエンコードする方法はありません。
しかし残念なことに、Scala Collection Library を使用すると、新しい豊富なデータ構造を少量の新しいコードで非常に迅速に実装できます。リクエストの実装は次のとおりです。
class ParticularHashMap[A, +B] private(buckets: Vector[List[(A, B)]]) extends Map[A, B]{
def this() = this(Vector.fill(ParticularHashMap.BucketsNo)(List.empty))
def get(key: A) = {
val bucket = buckets(bucketIndex(key))
bucket match {
case List((_, v)) => Some(v) //YOUR SPECIAL OPTIMIZATION !
case list => list.find(key == _._1).map(_._2)
}
}
def iterator = buckets.flatten.iterator
def -(key: A) = mkWithUpdatedBucket(key, _ filterNot (_._1 == key))
def +[B1 >: B](kv: (A, B1)) = mkWithUpdatedBucket(kv._1, insert(kv._1, kv._2.asInstanceOf[B], _))
//if you're wondering why it's Bucket[A, Any] and not Bucket[A, B] it's because of the covariance of B
private def mkWithUpdatedBucket(key: A, f: Bucket[A, Any] => Bucket[A, Any]) = {
val index = bucketIndex(key)
val newBucket = f(buckets(index))
(new ParticularHashMap[A, Any](buckets.updated(index, newBucket))).asInstanceOf[ParticularHashMap[A, B]]
}
private def insert(k: A, v: Any, bucket: List[(A, Any)]): Bucket[A, Any] = bucket match {
case List() => List((k, v))
case (k1, v1) :: kvs if k == k1 => (k, v) :: kvs
case (k1, v1) :: kvs => (k1, v1) :: insert(k, v, kvs)
}
private def bucketIndex(key: A) = Math.abs(key.hashCode()) % ParticularHashMap.BucketsNo
}
object ParticularHashMap {
private val BucketsNo = 256
private type Bucket[+A, +B] = List[(A, B)]
def apply[A, B](kvs: (A, B)*) = new ParticularHashMap[A, B] ++ kvs
}
これは単純な実装であることに注意してください。ただし、ニーズに合わせて改善することもできます。
期待どおりに動作します:
val myMap = ParticularHashMap("hello" -> 2, "world" -> 4)
println(myMap.get("hello")) >> Some(2)
println(myMap.get("world")) >> Some(4)
println(myMap.get("world1")) >> None
ただし、もちろん、契約を尊重しないと、悪いことが起こることに注意してください。以下は、欠点を示すために特別に作成された例です。
val evilMap = ParticularHashMap(1 -> 2)
println(evilMap.get(1)) >> Some(2)
println(evilMap.get(257)) >> Some(2) //BUT 257 IS NOT IN THE MAP !!!