HashSet contient problème avec des objets personnalisés
Ma classe Personnalisée qui sera contenue par HashSet
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"hashcode='" + this.hashCode() + '\'' +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
if (!name.equals(person.name)) return false;
return true;
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Mon HashSet test qui échoue
public void hashSetTest() {
Set<Person> personSet = new HashSet<Person>();
Person p1 = new Person("raghu", 12);
Person p2 = new Person("rimmu", 21);
personSet.add(p1);
personSet.add(p2);
p1.setName("raghus");
p1.setAge(13);
int i2 =p1.hashCode();
System.out.println(personSet.size() + ": "+ p1.hashCode()+" : "+personSet.contains(p1)+ " : "+i2);
}
Iam attend personSet.contient(p1) pour passer. Pourquoi est-il de retour faux?
Merci
sri
OriginalL'auteur sridhar | 2011-02-24
Vous devez vous connecter pour publier un commentaire.
Parce que
p1.hashCode()
change lorsque vous modifiezp1
, de sorte qu'il ne peut pas être trouvé lors de son index dans la table de hachage plus. Ne laissez jamais une valeur de hachage dépend d'un champ mutable.(Vous êtes assez chanceux qu'il ne parvient pas pendant le test; il pourrait tout aussi bien avoir réussi, seulement à l'échec dans la production.)
cela peut être une question de style et de préférence, mais je serais encore dire jamais. Les fonctions de hachage doit être défini sur la base de l'immuable parties d'un objet. (Je ferais un objet léger comme cela a complètement immuable, mais alors je n'aime pas les setters).
C'est sûrement un piège que vous avez à être au courant, mais si vous avez besoin d'un accès efficace (~O(1)) à mutable objets il n'y a pas beaucoup que vous pouvez faire. Je veux dire que vous pourriez faire de les objets immuteable et en créer un nouveau et ajouter et supprimer l'ancien mais alors, qui mieux que les autres?
Vous devez marquer sa réponse comme correcte (le drapeau vert en plus de la/downvote).
Merci pour les réponses rapides. Êtes-vous les gars en disant que oringinal p1 objet avec HashCode xxxx au lieu de dire '1' dans la table de hachage est encore indexé au même endroit, à '1' dans la table de hachage avec un autre HashCode aaaa après une modification? C'est pourquoi contient méthode est en fait de ne pas trouver l'objet p1 dans son ensemble, parce que maintenant HashCode aaaa est de montrer un autre indice? --sri
OriginalL'auteur Fred Foo
HashSet implémente Ensemble. Le ApiDoc spécifie:
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.
Dans votre exemple, c'est le cas, car le changement de
name
ouage
surp1
affecte l'égalité de comparaison. Ainsi, selon le ApiDoc, le comportement de Jeu dans votre cas n'est pas spécifié.OriginalL'auteur Michael Konietzka
Je pense que vous devez avoir hashCode dépend de champs mutables assez souvent, en effet: lorsque vous remplacez des égaux qui dépend de champs mutables.
De hashCode du contrat: "Si deux objets sont égaux selon la equals(Object) méthode, puis en appelant la méthode hashCode sur chacun des deux objets doit produire le même résultat sous forme d'entier."
Donc, si vous créez deux objets tels que A. equals(B) est vrai, et puis de modifier Une telle manière que vous obtenez A. equals(B) sont devenus de faux, vous avez besoin d'avoir hashCodes changement trop.
Il est vrai que dans le hashCode de la documentation est indiqué qu ' "Il n'est pas nécessaire que si deux objets sont inégales selon les equals(java.lang.Objet) méthode, puis en appelant la méthode hashCode sur chacun des deux objets doivent produire integer distinctes résultats.", mais je ne sais pas comment cela peut aider.
OriginalL'auteur think01
Les hachages sont couplage simple de clés et de valeurs. Voici comment l'état de votre code avant et après le changement de nom en pseudo-code:
Avant:
Après:
Puisque vous avez un accès direct à la p1 de l'objet dans le HashSet est correctement mis à jour, mais HashSet ne fait pas attention aux objets contenus hashcodes cours de mise à jour. Lors d'un appel
personSet.contains(p1)
est appelée, le HashSet à la recherche d'un entrée de gamme avec la nouvelle valeur dep1.hashcode()
.La
p1
objet est associé avec son précédent hashcode au moment où il a été ajouté à la HashSet.OriginalL'auteur trisrael