Veuillez clarifier mon doute dans Hashset. Considérez 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));
}
}
en principal 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 à hashset
Set<Person> sset=new HashSet<Person>();
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj3);
Je reçois 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 seule fois pour vérifier obj3 et obj4? Pourquoi ce n'est pas vérifié pour le reste des objets?
Question 2: Si la réponse est parce qu'ils ont tous les deux le même code de hachage, alors seulement les égaux seront appelés, alors pourquoi ce n'est pas appelé pour le code ci-dessous
sset.add(obj1);
sset.add(obj4);
sset.add(obj2);
sset.add(obj4);
la sortie est:
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: J'ai itéré la valeur ci-dessus et imprimé le contenu mais ni hachage ni égal n'ont été appelés. quand il est vraiment utile de remplacer le hashcode et la méthode equals?
Question 4: Quand est-ce que hashCode()
et equals()
seront appelés?
equals
si hashCode
diffère.hashCode
si (obj1 == obj2)
.hashCode
et/ou equals
juste pour itérer - vous ne comparez pas les objetsJe pense que toutes vos questions recevront une réponse si vous comprenez comment fonctionnent les Sets, et en particulier les HashSets. Un ensemble est une collection d'objets uniques, avec Java définissant l'unicité en ce qu'il ne correspond à rien d'autre (est égal à false).
Le HashSet profite des codes de hachage pour accélérer les choses. Il suppose que deux objets égaux auront le même code de hachage. Cependant, cela ne suppose pas que deux objets avec le même code de hachage signifient qu'ils sont égaux. C'est pourquoi, lorsqu'il détecte un code de hachage entrant en collision, il ne compare avec d'autres objets (dans votre cas, un) dans l'ensemble avec le même code de hachage.
selon le code source jdk de javasourcecode.org, HashSet utilise HashMap comme implémentation 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 tout d'abord de vérifier le hachage, puis de vérifier la référence et ensuite la méthode call equals de l'objet sera insérée.
Parce que dans le deuxième cas, vous ajoutez deux fois la même référence et HashSet
vérifiez 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
ne sera appelé que si le hachage de la clé ajoutée est égal à la clé déjà présente dans set et les références de ces deux sont différentes.
Vous devriez lire comment vous assurer que vous avez correctement implémenté equals et hashCode. C'est un bon point de départ: Quels sont les problèmes à prendre en compte lors de la substitution d'equals et de hashCode en Java?