据我所知,这种数据结构并不存在,因为它不安全——没有办法可靠地编码您的特定条件。
但是,可惜的是,Scala 集合库允许使用少量新代码非常快速地实现新的丰富数据结构。这是您的请求的实现:
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 !!!