Hashcode et égal pour Hashset
veuillez clarifier mon doute dans Hashset. Prenons le code suivant:
class Person
{
String name;
Person(String n)
{
name=n;
}
public String getName()
{
return name;
}
@Override
public boolean equals(Object arg0) {
System.out.println("in equals");
Person obj=(Person)arg0;
System.out.println("1st "+getName());
System.out.println("2nd "+obj.getName());
if(this.getName().equals(obj.getName()))
{
return true;
}
return false;
}
@Override
public int hashCode() {
System.out.println("in hash code");
System.out.println(" value is "+Integer.valueOf(name.charAt(0)));
return Integer.valueOf(name.charAt(0));
}
}
j'ai le code suivant
Person obj1=new Person("bcd");
Person obj2=new Person("cde");
Person obj3=new Person("abc");
Person obj4=new Person("abc");
maintenant si j'ajoute ces objets au hashset
Set<Person> sset=new HashSet<Person>();
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj3);
j'obtiens cette sortie
in hash code
value is 98
in hash code
value is 97
in hash code
value is 99
in hash code
value is 97
in equals
1st abc
2nd abc
Question 1 : pourquoi la fonction equals() n'est appelée qu'une fois pour vérifier obj3 et obj4 ? Pourquoi il n'est pas vérifié pour le reste de la les objets ?
Question 2 : si la réponse est qu'ils ont tous les deux le même code de hachage, alors seulement des égaux seront appelés, alors pourquoi il n'est pas appelé pour le code ci-dessous
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj4);
sortie:
in hash code
value is 98
in hash code
value is 97
in hash code
value is 99
in hash code
value is 97
il ne va pas à l'intérieur de la méthode equals() même si deux mêmes objets sont ajoutés à l'ensemble de hachage qui a le même code de hachage.
Question 3 : au-dessus de la valeur et imprimé le contenu mais ni hashcode ni égal n'ont été appelés. quand est-ce vraiment utile pour outrepasser hashcode et méthode égale?
Question 4 : quand appellera-t-on hashCode()
et equals()
?
6 réponses
- il n'est pas nécessaire d'appeler
equals
sihashCode
diffère. - il n'est pas nécessaire d'appeler
hashCode
si(obj1 == obj2)
. - il n'y a pas besoin de
hashCode
et/ouequals
juste pour itérer-vous ne comparez pas des objets - Lorsqu'il est nécessaire de distinguer entre les objets.
je pense que vos questions seront toutes répondues si vous comprenez comment les ensembles, et en particulier les HashSets fonctionnent. Un ensemble est une collection d'objets uniques, avec Java définissant l'unicité en ce qu'il n'égale rien d'autre (equals retourne false).
le HashSet profite des hashcodes pour accélérer les choses. Il suppose que deux objets égaux l'un à l'autre auront le même code de hachage. Cependant, il ne suppose pas que deux objets avec le même code de hachage signifient ils sont égaux. C'est pourquoi, lorsqu'il détecte une collision code de hachage, il ne se compare avec d'autres objets (dans votre cas) dans l'ensemble avec le même code de hachage.
selon le code source de jdk javasourcecode.org, HashSet utiliser HashMap comme sa mise en œuvre interne, le code sur la méthode put de HashSet est ci-dessous:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
la règle est d'abord de vérifier le hachage, puis de vérifier la référence et ensuite appel égal à la méthode de l'objet sera placé.
parce que dans le deuxième cas, vous ajoutant la même référence deux fois et HashSet
ont coché contre cela dans HashMap.put()
sur lequel HashSet
est basé:
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
comme vous pouvez le voir, equals
sera appelé seulement si le hachage de la clé ajoutée est égal à la clé déjà présente dans l'ensemble et les références de ces deux sont différentes.
vous devriez lire sur la façon de vous assurer que vous avez mis en œuvre égaux et hashCode correctement. C'est un bon point de départ: quelles sont les questions à prendre en compte lors de la suppression des équivalents et du hashCode en Java?
veuillez déboguer le HashSet avec toutes ses méthodes et vous verrez comment il fonctionne