Mise à jour de la clé Java HashMap
Je me demandais juste, qu'arriverait-il si la clé d'un HashMap
est mutable, le programme de test ci-dessous démontrent que et je suis incapable de le comprendre lorsque les deux d'égal à égal et hashCode
méthodes retourne
vrai et la même valeur, pourquoi ne hashmap.containsKey
retour false
.
public class MutableKeyHashMap {
public static void main(String []a){
HashMap<Mutable, String> map = new HashMap<Mutable, String>();
Mutable m1 = new Mutable(5);
map.put(m1, "m1");
Mutable m2 = new Mutable(5);
System.out.println(map.containsKey(m2));
m2.setA(6);
m1.setA(6);
Mutable m3 = map.keySet().iterator().next();
System.out.println(map.containsKey(m2)+" "+m3.hashCode()+" "+m2.hashCode()+" "+m3.equals(m2));
}
}
class Mutable {
int a;
public Mutable(int a) {
this.a = a;
}
@Override
public boolean equals(Object obj) {
Mutable m = (Mutable) obj;
return m.a == this.a ? true : false;
}
@Override
public int hashCode(){
return a;
}
public void setA(int a) {
this.a = a;
}
public int getA() {
return a;
}
}
Cette sortie :
vrai
faux 6 6 vrai
source d'informationauteur Abidi
Vous devez vous connecter pour publier un commentaire.
La javadoc explique
Fondamentalement, ne pas utiliser mutable objets comme des clés dans une Carte, vous allez être brûlé
D'extrapoler, car les docs peuvent ne pas apparaître clairement, je crois que le point pertinent ici est `a changé en une manière qui affecte égaux", et vous semblez être en supposant que equals(Object) est appelée à chaque fois que contient est invoquée. Les docs ne le dis pas, la formulation implique qu'ils peuvent être autorisés à mettre en cache les calculs.
À la recherche à la sourceil semble que, parce que votre hashCode renvoie une valeur différente (a 5, 6), il est possible qu'il soit recherché dans un autre compartiment basé sur les détails d'implémentation.
Vous pouvez penser si de cette façon, la Carte a 16 seaux. Quand vous donnez un objet A == 5, il la jette dans le seau de 5. Maintenant, vous pouvez changer à 6, mais il est encore dans le seau de 5. La Carte ne vous connaissent pas changé, il n'a pas réorganiser les choses en interne.
Maintenant vous venez avec un autre objet avec Une == 6, et vous demandez à la Carte si elle a un de ces. Il va dans un seau 6 et dit: "Non, rien." Il ne va pas à aller vérifier tous les seaux pour vous.
De toute évidence la façon dont les choses se mettre dans des compartiments est plus compliqué que ça, mais c'est la façon dont il fonctionne dans le noyau.
La
HashMap
met votre objet à l'emplacement pour la clé de hachage5
. Ensuite, vous modifiez la clé de6
et l'utilisationcontainsKey
à demander la carte si elle contient l'objet. La carte ressemble à la position6
et ne trouve rien, donc il répondfalse
.Afin de ne pas le faire, alors.
Quand vous mettez "m1" la première fois autour,
hashCode()
était de 5. Ainsi, leHashMap
utilisé 5 placer la valeur appropriée dans le seau. Après un changement dem2
lehashCode()
a 6, de sorte que lorsque vous avez essayé la recherche de la valeur que vous mettez, il le seau regardé en a été différent.Un exemple de code pour accompagner ptomli's réponse.
Compile et s'exécute. Le résultat est:
J'utilise la version 6 de Java sur Linux.