Ceci est une amélioration de la première solution proposée par @cheeken. Je suggère chaudement de ne pas adopter la seconde, sauf si vous travaillez sur un projet trivial. Avec la deuxième approche, vous ne pouvez pas faire en sorte que tous les éléments que vous avez placés dans la carte aient leur hachage calculé avec le même hachage, ce qui peut conduire à un comportement incorrect et inattendu difficile à expliquer à l'exécution.
La bonne façon de faire est de prendre ispiration de la HashMap dans la bibliothèque Scala:
@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)
}
Si vous regardez, vous pouvez simplement écrire la classe suivante:
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)
}
Vous devez être Assurez-vous que toutes les méthodes publiques se comportent correctement, y compris par (vous devez implémenter une carte de hachage parallèle qui utilise votre hachage spécial) et fusionner, ainsi que le vide, qui ne doit pas renvoyer HashMap.empty[A,B]
mais CustomHashMap.empty[A,B]
Est-ce que vous définissez 'hashCode()' et 'equals()' uniquement pour les besoins de la compatibilité 'Map'? – cheeken
@cheeken 'HashSet' est également utilisé, mais fondamentalement pour ce genre de collections. – Kane