这是对@cheeken 提出的第一个解决方案的改进。我强烈建议不要采用第二种,除非你正在做一个琐碎的项目。使用第二种方法,您不能强制您放入地图中的所有项目都使用相同的哈希计算它们的哈希,这可能会导致错误和意外的行为,这在运行时很难解释。
正确的方法是从 Scala 库中的 HashMap 中获取灵感:
@SerialVersionUID(2L)
class HashMap[A, +B] extends Map[A,B] with MapLike[A, B, HashMap[A, B]] with Serializable with CustomParallelizable[(A, B), ParHashMap[A, B]] {
override def size: Int = 0
override def empty = HashMap.empty[A, B]
def iterator: Iterator[(A,B)] = Iterator.empty
override def foreach[U](f: ((A, B)) => U): Unit = { }
def get(key: A): Option[B] =
get0(key, computeHash(key), 0)
override def updated [B1 >: B] (key: A, value: B1): HashMap[A, B1] =
updated0(key, computeHash(key), 0, value, null, null)
override def + [B1 >: B] (kv: (A, B1)): HashMap[A, B1] =
updated0(kv._1, computeHash(kv._1), 0, kv._2, kv, null)
override def + [B1 >: B] (elem1: (A, B1), elem2: (A, B1), elems: (A, B1) *): HashMap[A, B1] =
this + elem1 + elem2 ++ elems
// TODO: optimize (might be able to use mutable updates)
def - (key: A): HashMap[A, B] =
removed0(key, computeHash(key), 0)
protected def elemHashCode(key: A) = key.##
protected final def improve(hcode: Int) = {
var h: Int = hcode + ~(hcode << 9)
h = h ^ (h >>> 14)
h = h + (h << 4)
h ^ (h >>> 10)
}
private[collection] def computeHash(key: A) = improve(elemHashCode(key))
protected type Merger[B1] = ((A, B1), (A, B1)) => (A, B1)
private[collection] def get0(key: A, hash: Int, level: Int): Option[B] = None
private[collection] def updated0[B1 >: B](key: A, hash: Int, level: Int, value: B1, kv: (A, B1), merger: Merger[B1]): HashMap[A, B1] =
new HashMap.HashMap1(key, hash, value, kv)
protected def removed0(key: A, hash: Int, level: Int): HashMap[A, B] = this
protected def writeReplace(): AnyRef = new HashMap.SerializationProxy(this)
def split: Seq[HashMap[A, B]] = Seq(this)
def merge[B1 >: B](that: HashMap[A, B1], merger: Merger[B1] = null): HashMap[A, B1] = merge0(that, 0, merger)
protected def merge0[B1 >: B](that: HashMap[A, B1], level: Int, merger: Merger[B1]): HashMap[A, B1] = that
override def par = ParHashMap.fromTrie(this)
}
如果你看,你可以只写下面的类:
class CustomHashMap[A,+B](val hashCalculator:HashCalculator[A]) extends HashMap[A,B] {
//protected def elemHashCode(key: A) = key.##
override def elemHashCode(key: A) = hashCalculator(key)
}
您必须确保所有公共方法的行为正确,包括 par (您需要实现使用特殊哈希器的并行哈希映射)和合并,以及不应该返回
HashMap.empty[A,B]
但CustomHashMap.empty[A,B]