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() ?

44
demandé sur MatTheWhale 2011-03-22 22:48:13

6 réponses

  1. il n'est pas nécessaire d'appeler equals si hashCode diffère.
  2. il n'est pas nécessaire d'appeler hashCode si (obj1 == obj2) .
  3. il n'y a pas besoin de hashCode et/ou equals juste pour itérer-vous ne comparez pas des objets
  4. Lorsqu'il est nécessaire de distinguer entre les objets.
48
répondu Erik 2018-03-09 11:12:44

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.

18
répondu Zugwalt 2011-03-22 19:54:11

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é.

11
répondu Sion.Cheng 2013-05-03 09:01:42

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.

2
répondu Victor Sorokin 2011-03-22 19:56:29

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?

1
répondu Greg 2017-05-23 12:10:05

veuillez déboguer le HashSet avec toutes ses méthodes et vous verrez comment il fonctionne

-3
répondu Yoni Roit 2011-03-22 19:55:20