Pourquoi dois-je outrepasser les méthodes equals et hashCode en Java?

récemment j'ai lu ceci Développeur Travaille Document .

le document est tout au sujet de définir hashCode() et equals() de façon efficace et correcte, mais je ne suis pas en mesure de comprendre pourquoi nous devons passer outre ces deux méthodes.

Comment puis-je prendre la décision de mettre en œuvre ces méthodes efficacement?

290
demandé sur Exploring 2010-02-15 14:17:59

29 réponses

Joshua Bloch dit sur Effective Java

vous devez outrepasser hashCode() dans chaque classe qui outrepasse égale(). Faute de quoi, il y aura violation du contrat général.hashCode (), qui empêchera votre classe de fonctionner correctement en conjonction avec toutes les collections basées sur le hachage, y compris HashMap, HashSet, et Hashtable.

essayons de comprendre avec un exemple de ce que se produirait si nous outrepassons equals() sans outrepasser hashCode() et tentons d'utiliser un Map .

disons que nous avons une classe comme celle-ci et que deux objets de MyClass sont égaux si leur importantField est égal (avec hashCode() et equals() généré par eclipse)

public class MyClass {

    private final String importantField;
    private final String anotherField;

    public MyClass(final String equalField, final String anotherField) {
        this.importantField = equalField;
        this.anotherField = anotherField;
    }

    public String getEqualField() {
        return importantField;
    }

    public String getAnotherField() {
        return anotherField;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((importantField == null) ? 0 : importantField.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final MyClass other = (MyClass) obj;
        if (importantField == null) {
            if (other.importantField != null)
                return false;
        } else if (!importantField.equals(other.importantField))
            return false;
        return true;
    }

}

remplacer seulement equals

si seulement equals est overriden, puis quand vous appelez myMap.put(first,someValue) premier hachage à un seau et quand vous appelez myMap.put(second,someOtherValue) il hachage à un autre seau (comme ils ont un différent hashCode ). Donc, bien qu'ils soient égaux, puisqu'ils ne se hasardent pas au même seau, la carte ne peut pas le réaliser et tous les deux restent dans la carte.


bien qu'il ne soit pas nécessaire d'outrepasser equals() si nous outrepassons hashCode() , voyons ce qui se passerait dans ce cas particulier où nous savons que deux objets de MyClass sont égaux si leur importantField est égal mais que nous n'outrepassons pas equals() .

Override " seulement hashCode

Imaginez que vous avez ceci

MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");

si vous outrepassez seulement hashCode alors quand vous appelez myMap.put(first,someValue) il prend d'abord, calcule son hashCode et le stocke dans un seau donné. Puis quand vous appelez myMap.put(second,someOtherValue) il devrait remplacer le premier par le second, conformément à la documentation cartographique parce qu'ils sont égaux (selon les exigences opérationnelles).

mais le problème est que les égaux n'a pas été redéfini, de sorte que lorsque la carte hache second et itère à travers le seau de recherche s'il ya un objet k tel que second.equals(k) est vrai, il ne sera pas trouver tout comme second.equals(first) sera false .

espérons était clair

435
répondu Lombo 2016-07-21 19:44:55

Collections telles que HashMap et HashSet utilisez la valeur hashcode d'un objet pour déterminer comment l'objet doit être stocké dans la collection, et le hashcode est utilisé à nouveau pour aider à localiser l'objet dans la collection.

"151940920 de" Hachage de récupération est un processus en deux étapes.

  1. trouver le seau droit (en utilisant le hashCode ())
  2. Rechercher dans le seau l'élément de droite (en utilisant equals() )

voici un petit exemple pour lequel nous devrions dépasser equals() et hashcode().Considérez une classe D'employés qui a deux champs âge et nom.

public class Employee {

    String name;
    int age;

    public Employee(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        if (!(obj instanceof Employee))
            return false;
        Employee employee = (Employee) obj;
        return employee.getAge() == this.getAge()
                && employee.getName() == this.getName();
    }

    // commented    
    /*  @Override
        public int hashCode() {
            int result=17;
            result=31*result+age;
            result=31*result+(name!=null ? name.hashCode():0);
            return result;
        }
     */
}

crée maintenant une classe, insère un objet employé dans un HashSet et teste si cet objet est présent ou non.

public class ClientTest {
    public static void main(String[] args) {
        Employee employee = new Employee("rajeev", 24);
        Employee employee1 = new Employee("rajeev", 25);
        Employee employee2 = new Employee("rajeev", 24);

        HashSet<Employee> employees = new HashSet<Employee>();
        employees.add(employee);
        System.out.println(employees.contains(employee2));
        System.out.println("employee.hashCode():  " + employee.hashCode()
        + "  employee2.hashCode():" + employee2.hashCode());
    }
}

il va imprimer

false
employee.hashCode():  321755204  employee2.hashCode():375890482

maintenant la méthode hashCode uncement (), exécutez la même et la sortie serait

true
employee.hashCode():  -938387308  employee2.hashCode():-938387308

Maintenant pouvez-vous voir pourquoi si deux objets sont considérés égaux, leurs hashcodes doivent également être égaux? Sinon, vous ne seriez jamais en mesure de trouver l'objet depuis le défaut la méthode hashcode dans l'objet de classe revient presque toujours avec un numéro unique pour chaque objet, même si la méthode equals() est dépassée de telle manière que deux ou plus objets sont considérés égaux. Peu importe à quel point les objets sont égaux si leurs hashcodes ne reflètent pas ça. Donc encore une fois: si deux objets sont égaux, leur hashcodes doit être égale.

141
répondu rajeev pani.. 2018-07-27 17:35:50

vous devez outrepasser hashCode () dans chaque classe qui remplace equals(). Échec pour ce faire entraînera une violation de le contrat général pour Objet.hashCode(), qui permettra d'éviter l' votre classe de fonctionner correctement en collaboration avec tous les base de hachage collections, y compris HashMap, HashSet, et Hashtable.



à partir de Effective Java , par Joshua Bloch

en définissant equals() et hashCode() de manière cohérente, vous pouvez améliorer l'utilisabilité de vos classes comme clés dans les collections basées sur le hash. Comme L'explique L'API doc pour hashCode: "cette méthode est supportée au profit de hashtables tels que ceux fournis par java.util.Hashtable ."

la meilleure réponse à votre question sur la façon de mettre en œuvre ces méthodes efficacement est de vous suggérer de lire le chapitre 3 de Java efficace .

47
répondu JuanZe 2016-08-24 12:53:02

simplement dit, la méthode des égaux dans la vérification D'objet pour l'égalité de référence, où comme deux instances de votre classe pourrait encore être sémantiquement égale quand les propriétés sont égales. Ceci est par exemple important lors de la mise de vos objets dans un conteneur qui utilise des égaux et des hashcodes, comme HashMap et Set . Disons que nous avons une classe comme:

public class Foo {
    String id;
    String whatevs;

    Foo(String id, String whatevs) {
        this.id = id;
        this.whatevs = whatevs;
    }
}

nous créons deux instances avec le même id :

Foo a = new Foo("id", "something");
Foo b = new Foo("id", "something else");

Sans écraser égal à égal, nous obtenons:

  • un.est égal à(b) est faux car ils sont deux instances différentes
  • A. equals (a) est vrai puisque c'est la même instance
  • B. equals (b) est vrai puisque c'est la même instance

Correct? Eh bien peut-être, si c'est ce que vous voulez. Mais disons que nous voulons objets avec le même id pour le même objet, qu'il s'agisse de deux instances différentes. Nous outrepassons les égaux (et hashcode):

public class Foo {
    String id;
    String whatevs;

    Foo(String id, String whatevs) {
        this.id = id;
        this.whatevs = whatevs;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Foo) {
            return ((Foo)other).id.equals(this.id);   
        }
    }

    @Override
    public int hashCode() {
        return this.id.hashCode();
    }
}

quant à la mise en œuvre des égaux et hashcode je peux recommander d'utiliser guava's helper methods

18
répondu crunchdog 2013-07-23 10:53:07

l'Identité n'est pas l'égalité.

  • signifie opérateur == identité d'essai.
  • equals(Object obj) méthode compare test d'égalité(c'est à dire, nous devons dire à l'égalité par la substitution de la méthode)

Pourquoi dois-je outrepasser les méthodes equals et hashCode en Java?

nous devons d'Abord comprendre l'utilisation méthode d'égal à égal.

afin d'identifier les différences entre deux objets, nous devons outrepasser la méthode equals.

par exemple:

Customer customer1=new Customer("peter");
Customer customer2=customer1;
customer1.equals(customer2); // returns true by JVM. i.e. both are refering same Object
------------------------------
Customer customer1=new Customer("peter");
Customer customer2=new Customer("peter");
customer1.equals(customer2); //return false by JVM i.e. we have two different peter customers.

------------------------------
Now I have overriden Customer class equals method as follows:
 @Override
    public boolean equals(Object obj) {
        if (this == obj)   // it checks references
            return true;
        if (obj == null) // checks null
            return false;
        if (getClass() != obj.getClass()) // both object are instances of same class or not
            return false;
        Customer other = (Customer) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name)) // it again using bulit in String object equals to identify the difference 
            return false;
        return true; 
    }
Customer customer1=new Customer("peter");
Customer customer2=new Customer("peter");
Insteady identify the Object equality by JVM, we can do it by overring equals method.
customer1.equals(customer2);  // returns true by our own logic

maintenant la méthode de hashCode peut comprendre facilement.

hashCode produit entier afin de stocker l'objet dans les structures de données comme HashMap , HashSet .

supposons que nous avons la méthode override equals de Customer comme ci-dessus,

customer1.equals(customer2);  // returns true by our own logic

tout en travaillant avec la structure de données lorsque nous stockons l'objet dans des seaux(bucket est un nom de fantaisie pour le dossier). Si nous utilisons la technique de hachage intégré, pour deux clients ci-dessus il génère deux hashcode différents. Nous stockons donc le même objet identique à deux endroits différents. Pour éviter ce genre de problèmes, nous devrions outrepasser la méthode hashCode également basée sur ce qui suit: principe.

  • de l'onu-l'égalité des cas, peuvent avoir le même hashcode.
  • les mêmes instances doivent retourner le même hashcode.
14
répondu Premraj 2018-06-25 02:28:32

Ok, laissez-moi vous expliquer le concept en termes très simples.

tout d'abord d'un point de vue plus large,nous avons des collections, et hashmap est l'une des infrastructures de données dans les collections.

pour comprendre pourquoi nous devons outrepasser la méthode à la fois égale et hashcode, s'il faut d'abord comprendre ce qui est hashmap et ce qui est fait.

un hashmap est une structure de données qui stocke des paires de valeurs clés de données en tableaux. Disons une[], où chaque élément de " a " est une paire de valeurs clés.

de plus, chaque indice du tableau ci-dessus peut être lié à une liste, ayant ainsi plus d'une valeur à un indice.

maintenant, pourquoi utilise-t-on un hashmap? Si nous devons chercher parmi un grand tableau, puis chercher à travers chacun si elles ne seront pas efficaces, alors ce que la technique de hachage nous dit qui permet pré traiter le tableau avec une certaine logique et grouper les éléments basés sur cette logique i.e. hachage

par exemple: nous avons de la matrice de 1,2,3,4,5,6,7,8,9,10,11 et on applique une fonction de hachage mod 10 1,11 seront regroupés ensemble. Donc, si nous devions chercher pour 11 dans le tableau précédent alors nous devrions itérer le tableau complet mais quand nous le Groupons nous limitons notre portée d'itération améliorant ainsi la vitesse. Cette infrastructure de données utilisée pour stocker toutes les informations ci-dessus peut être considérée comme un tableau 2d pour la simplicité

maintenant en dehors du hashmap ci-dessus dit aussi qu'il ne va pas ajouter de doublons dedans. Et c'est la raison principale pour laquelle nous devons outrepasser les égaux et le hashcode

ainsi quand son dit qui expliquent le fonctionnement interne de hashmap , nous devons trouver quelles méthodes le hashmap A et comment il suit les règles ci-dessus que j'ai expliqué ci-dessus

ainsi le hashmap a la méthode appelée as put (K,V) , et selon hashmap il doit suivre les règles ci-dessus pour distribuer efficacement le tableau et ne pas ajouter de doublons

donc ce que put fait est qu'il va d'abord générer le hashcode pour la clé donnée pour décider quel index la valeur doit entrer.si rien n'est présent à l'index alors la nouvelle valeur sera ajoutée au-dessus de là, si quelque chose est déjà présente là-bas puis la nouvelle valeur doit être ajoutée après la fin de la liste liée à l'index. mais rappelez-vous qu'aucun duplicata ne doit être ajouté selon le comportement désiré du hashmap. donc, disons que vous avez deux Entiers objets aa=11,b=11. comme chaque Objet dérivé de la classe objet, l'implémentation par défaut pour comparer deux objets est qu'elle compare la référence et non les valeurs à l'intérieur de l'objet. Donc, dans le cas ci-dessus, bien que sémantiquement égaux échouera le test d'égalité, et la possibilité que deux objets qui hashcode même et les mêmes valeurs existeront créant ainsi des doublons. Si nous annulons alors nous pourrions éviter d'ajouter des doublons. Vous pouvez également vous référer à détail de travail

import java.util.HashMap;


public class Employee {

String name;
String mobile;
public Employee(String name,String mobile) {
    this.name=name;
    this.mobile=mobile;
}

@Override
public int hashCode() {
    System.out.println("calling hascode method of Employee");
    String str=this.name;
    Integer sum=0;
    for(int i=0;i<str.length();i++){
        sum=sum+str.charAt(i);
    }
    return sum;

}
@Override
public boolean equals(Object obj) {
    // TODO Auto-generated method stub
    System.out.println("calling equals method of Employee");
    Employee emp=(Employee)obj;
    if(this.mobile.equalsIgnoreCase(emp.mobile)){

        System.out.println("returning true");
        return true;
    }else{
        System.out.println("returning false");
        return false;
    }


}

public static void main(String[] args) {
    // TODO Auto-generated method stub

    Employee emp=new Employee("abc", "hhh");
    Employee emp2=new Employee("abc", "hhh");
    HashMap<Employee, Employee> h=new HashMap<>();
    //for (int i=0;i<5;i++){
        h.put(emp, emp);
        h.put(emp2, emp2);

    //}

    System.out.println("----------------");
    System.out.println("size of hashmap: "+h.size());


}

}
11
répondu Chetan 2015-03-03 18:33:17

hashCode() :

si vous ne modifiez que la méthode hash-code, il ne se passera rien. Parce qu'il renvoie toujours le nouveau hashCode pour chaque objet en tant que Classe D'objet.

equals() :

si vous outrepassez seulement la méthode d'égalité, a.equals(b) est vrai cela signifie que le hashCode de a et b doit être le même mais ne se produit pas. Parce que vous n'avez pas outrepassé la méthode hashCode .

Note: hashCode() méthode de la classe D'objet toujours retourner le nouveau hashCode pour chaque objet.

Ainsi, lorsque vous devez utiliser votre objet dans la collection basée sur le hachage, doit remplacer à la fois equals() et hashCode() .

11
répondu Rinkal Gupta 2016-03-25 10:50:23

afin d'utiliser nos propres objets de classe comme clés dans les collections comme HashMap, Hashtable etc.. , nous devrions outrepasser les deux méthodes (hashCode () et equals ()) en ayant une conscience sur le travail interne de collecte. Dans le cas contraire, cela conduit à des résultats erronés auxquels nous ne sommes pas attendus.

6
répondu Prashanth - codeforeach.com 2014-03-11 09:38:54

parce que si vous ne les annulez pas, vous utiliserez l'implantation par défaut dans L'objet.

étant donné que l'égalité d'instance et les valeurs hascode exigent généralement la connaissance de ce qui constitue un objet, ils auront généralement besoin d'être redéfinis dans votre classe pour avoir un sens tangible.

5
répondu PaulJWilliams 2010-02-15 11:20:56

Java met une règle que

" si deux objets sont égaux en utilisant la méthode Classe d'objet égale, alors la méthode hashcode devrait donner la même valeur pour ces deux objets."

donc, si dans notre classe nous outrepassons égal, nous devrions outrepasser la méthode hashcode aussi pour faire tomber cette règle. Ces deux méthodes equals et hashcode sont utilisées dans Hashtable pour stocker des valeurs comme paire de valeurs clés.Si nous en outrepassons un et non l'autre, il y a une possibilité que le hashtable ne fonctionne pas comme nous le voulons, si nous utilisons un tel objet comme clé.

5
répondu Ritesh Kaushik 2014-01-01 15:13:07

ajoute à la réponse de @Lombo

quand devrez-vous outrepasser equals() ?

l'implémentation par défaut des égaux D'objet () est

public boolean equals(Object obj) {
        return (this == obj);
}

ce qui signifie que deux objets seront considérés égaux seulement s'ils ont la même adresse mémoire qui sera vraie seulement si vous êtes la comparaison d'un objet avec lui-même.

mais vous pourriez envisager de deux objets de même s'ils ont la même valeur pour un ou plus de leurs propriétés (voir l'exemple donné dans la réponse de @Lombo).

donc vous annulerez equals() dans ces situations et vous donnerez vos propres conditions pour l'égalité.

j'ai mis en œuvre avec succès equals() et cela fonctionne très bien.Alors, pourquoi demandent-ils d'outrepasser hashCode ()?

bien.Tant que vous n'utilisez pas "collections à base de Hash" sur votre classe définie par l'utilisateur,c'est très bien. Mais à un certain moment dans le futur vous pourriez vouloir utiliser HashMap ou HashSet et si vous ne override et "implémentez correctement" hashCode() , ces collections basées sur le Hash ne fonctionneront pas comme prévu.

Remplacer seulement equals (Plus de @Lombo 's réponse)

myMap.put(first,someValue)
myMap.contains(second); --> But it should be the same since the key are the same.But returns false!!! How?

tout d'abord, HashMap vérifie si le hashCode de second est le même que first . Seulement si les valeurs sont les mêmes,il va procéder à la vérification de l'égalité dans le même seau.

mais ici le hashCode est différent pour ces 2 objets (parce qu'ils ont une adresse mémoire différente-de l'implémentation par défaut). Par conséquent, il ne se souciera même pas de vérifier l'égalité.

si vous avoir un point de rupture à l'intérieur de votre méthode overridden equals (), il n'interviendrait pas s'ils ont des hashCodes différents. contains() vérifie hashCode() et seulement s'ils sont identiques, il appellerait votre méthode equals() .

pourquoi ne pouvons-nous pas faire le contrôle de HashMap pour l'égalité dans tous les seaux? Il n'y a donc aucune nécessité pour moi d'outrepasser hashCode() !!

alors vous manquez le point de hachage Collections basées. Considérons ce qui suit :

Your hashCode() implementation : intObject%9.

ce qui suit sont les clés stockées sous forme de seaux.

Bucket 1 : 1,10,19,... (in thousands)
Bucket 2 : 2,20,29...
Bucket 3 : 3,21,30,...
...

Dites,vous voulez savoir si la carte contient la clé de 10. Souhaitez-vous souhaitez rechercher tous les seaux? ou voulez-vous rechercher un seul seau?

basé sur le hashCode,vous pouvez identifier que si 10 est présent,il doit être présent dans le seau 1. Seul Bucket 1 sera fouillé !!

5
répondu user104309 2014-12-09 06:14:37
class A {
    int i;
    // Hashing Algorithm
    if even number return 0 else return 1
    // Equals Algorithm,
    if i = this.i return true else false
}
  • put ('key',' value') calculera la valeur de hachage en utilisant hashCode() pour déterminer seau et utilise la méthode equals() pour déterminer si la valeur est déjà présent dans le Seau. Si non, il sera ajouté sinon, il sera remplacé par la valeur courante
  • get('key') va utiliser hashCode() pour trouver l'Entrée (seau) en premier et equals() pour trouver la valeur de L'entrée

si les deux sont dépassés,

Carte< A >

Map.Entry 1 --> 1,3,5,...
Map.Entry 2 --> 2,4,6,...

si equals n'est pas surchargé

Carte< A >

Map.Entry 1 --> 1,3,5,...,1,3,5,... // Duplicate values as equals not overridden
Map.Entry 2 --> 2,4,6,...,2,4,..

si le hashCode n'est pas dépassé

Carte< A >

Map.Entry 1 --> 1
Map.Entry 2 --> 2
Map.Entry 3 --> 3
Map.Entry 4 --> 1
Map.Entry 5 --> 2
Map.Entry 6 --> 3 // Same values are Stored in different hasCodes violates Contract 1
So on...

HashCode L'Égalité De Contrat

  1. deux touches égales selon la même méthode devraient générer le même hashCode
  2. deux clés générant le même hashCode ne doivent pas être égales (dans l'exemple ci-dessus, tous les nombres pairs génèrent le même code de hachage)
5
répondu bharanitharan 2015-07-14 09:31:58

Equals et Hashcode méthodes en Java

ce sont des méthodes de java.lang.Classe objet qui est la classe super de toutes les classes (classes personnalisées ainsi que d'autres définies dans L'API java).

mise en Œuvre:

public boolean equals (Object obj)

hashCode public int ()

enter image description here

public boolean equals (Object obj)

cette méthode vérifie simplement si deux références d'objet x et y se rapportent au même objet. c'est-à-dire qu'il vérifie si x == Y.

Il est réflexive: pour toute valeur de référence x, x.est égal à(x) doit retourner true.

il est symétrique: pour toute valeurs de référence x et y, X. equals (y) devrait retourner true si et seulement si Y. equals (x) retourne true.

it is transitive: for any reference values x, y, and z, if X. equals (y) retourne true et Y. equals (z)retourne true, puis X. equals (z) should return true.

C'est cohérent: pour toutes les valeurs de référence x et y, de multiples appels de x.equals(y) retourne true ou constante de retour faux, pourvu qu'aucune information utilisée dans les comparaisons égales sur l'objet ne soit modifiée.

pour toute valeur de référence non nulle x, X. equals (null) devrait retourner faux.

public int hashCode ()

cette méthode renvoie la valeur du code de hachage de l'objet sur lequel cette méthode est invoquée. Cette méthode retourne la valeur du code de hachage comme un entier et est supportée au profit de classes de collection basées sur le hachage telles que Hashtable, HashMap, HashSet etc. Cette méthode doit être écrasée dans chaque classe qui l'emporte sur la méthode equal.

le contrat général du hashCode est:

chaque fois qu'elle est invoquée sur le même objet plus d'une fois lors de l'exécution D'une application Java, la méthode hashCode doit systématiquement retourner le même entier, à condition qu'aucune information utilisée dans les comparaisons égales sur l'objet est modifié.

cet entier n'a pas besoin de rester cohérent d'une exécution d'une application à une autre exécution de la même application.

si deux objets sont égaux selon la méthode equals(Object), alors appeler la méthode hashCode sur chacun des deux objets doit produire le même résultat entier.

il n'est pas nécessaire que si deux objets sont inégaux selon les égaux(java.lang.Objet) méthode, puis en appelant la la méthode de hashCode sur chacun des deux objets doit produire des résultats entiers distincts. Cependant, le programmeur doit être conscient que la production de résultats entiers distincts pour les objets inégaux peut améliorer la performance des hashtables.

objets égaux doivent produire le même code de hachage aussi longtemps qu'ils sont les objets égaux, cependant inégaux n'ont pas besoin de produire des codes de hachage distincts.

ressources:

JavaRanch

Image

5
répondu Aftab Virtual 2016-08-28 06:13:51

considérez collection de balles dans un seau tout en couleur Noire. Votre travail est de colorer ces boules comme suit et de l'utiliser pour le jeu approprié,

Pour Tennis-Jaune, Rouge. Pour Cricket-Blanc

maintenant bucket a des couilles en trois couleurs Jaune, Rouge et blanc. Et que maintenant vous avez fait la coloration que vous savez quelle couleur est pour quel jeu.

colorer les balles-Hashing. Choisir la balle pour jeu Égal.

si vous avez fait la coloration et que quelqu'un choisit la balle pour le cricket ou le tennis, ils ne se soucieront pas de la couleur!!!

4
répondu bharanitharan 2015-07-09 06:02:47

je regardais dans l'explication "si vous outrepassez hashCode puis quand vous appelez myMap.put(first,someValue) il prend d'abord, calcule son hashCode et le stocke dans un seau donné. Ensuite, lorsque vous appelez myMap.put(first,someOtherValue) , il doit remplacer le premier par le second, conformément à la Documentation de la carte, car ils sont égaux (selon notre définition).":

je pense que la deuxième fois quand nous ajoutons dans myMap alors il devrait être le 'second' objet comme myMap.put(second,someOtherValue)

4
répondu Narinder 2016-03-25 10:10:24

Il est utile lors de l'utilisation de Objets de Valeur . Ce qui suit est un extrait du Portland Pattern Repository :

Exemples d'objets de valeur sont des choses comme les nombres, les dates, l'argent et chaîne. Généralement, ils sont petits objets qui sont utilisés assez largement. Leur identité est basée sur leur état plutôt que sur leur identité de l'objet. De cette façon, vous pouvez avoir plusieurs copies du même objet de valeur conceptuelle.

donc je peux avoir plusieurs copies d'un objet qui représente la date du 16 janvier 1998. N'importe laquelle de ces copies sera égale à l'autre. Pour un petit l'objet de ce type, il est souvent plus facile d'en créer de nouveaux et de les déplacer autour plutôt que de compter sur un objet unique pour représenter la date.

un objet de valeur doit toujours avoir priorité .equals () en Java (ou = en Smalltalk). (Rappelez-vous d'annuler .hashCode() bien.)

3
répondu Ionuț G. Stan 2010-02-15 11:24:51

les méthodes égalent et le hashcode est défini dans la classe objet. Par défaut si la méthode equals retourne true, alors le système ira plus loin et vérifiera la valeur du code de hachage. Si le code de hachage des 2 objets est également le même, alors les objets seront considérés comme identiques. Ainsi, si vous outrepassez seulement la méthode equals, alors même si la méthode overridden equals indique que 2 objets sont égaux, le hashcode défini par le système peut ne pas indiquer que les 2 objets sont égaux. Nous avons donc besoin d' pour remplacer le code de hachage.

3
répondu Aarti 2013-07-28 08:06:24

supposons que vous avez la classe (A) qui regroupe deux autres (B) (C), et que vous devez stocker les instances de (A) dans le hashtable. La mise en œuvre par défaut permet seulement de distinguer les instances, mais pas par (B) et (c). Ainsi, deux instances de A pourraient être égales, mais la valeur par défaut ne vous permettrait pas de les comparer correctement.

2
répondu Dewfy 2010-02-15 11:22:07

dans l'exemple ci-dessous, si vous commentez le outrepasser pour égal ou hashcode dans la classe Personne, ce code manquera de vérifier L'ordre de Tom. L'utilisation de l'implémentation par défaut du hashcode peut causer des échecs dans les recherches du hashtable.

ce que j'ai ci-dessous est un code simplifié qui établit l'ordre des gens par personne. La personne est utilisée comme clé dans le hashtable.

public class Person {
    String name;
    int age;
    String socialSecurityNumber;

    public Person(String name, int age, String socialSecurityNumber) {
        this.name = name;
        this.age = age;
        this.socialSecurityNumber = socialSecurityNumber;
    }

    @Override
    public boolean equals(Object p) {
        //Person is same if social security number is same

        if ((p instanceof Person) && this.socialSecurityNumber.equals(((Person) p).socialSecurityNumber)) {
            return true;
        } else {
            return false;
        }

    }

    @Override
    public int hashCode() {        //I am using a hashing function in String.java instead of writing my own.
        return socialSecurityNumber.hashCode();
    }
}


public class Order {
    String[]  items;

    public void insertOrder(String[]  items)
    {
        this.items=items;
    }

}



import java.util.Hashtable;

public class Main {

    public static void main(String[] args) {

       Person p1=new Person("Tom",32,"548-56-4412");
        Person p2=new Person("Jerry",60,"456-74-4125");
        Person p3=new Person("Sherry",38,"418-55-1235");

        Order order1=new Order();
        order1.insertOrder(new String[]{"mouse","car charger"});

        Order order2=new Order();
        order2.insertOrder(new String[]{"Multi vitamin"});

        Order order3=new Order();
        order3.insertOrder(new String[]{"handbag", "iPod"});

        Hashtable<Person,Order> hashtable=new Hashtable<Person,Order>();
        hashtable.put(p1,order1);
        hashtable.put(p2,order2);
        hashtable.put(p3,order3);

       //The line below will fail if Person class does not override hashCode()
       Order tomOrder= hashtable.get(new Person("Tom", 32, "548-56-4412"));
        for(String item:tomOrder.items)
        {
            System.out.println(item);
        }
    }
}
2
répondu developer747 2016-03-24 13:25:21

1) l'erreur courante est illustrée dans l'exemple ci-dessous.

public class Car {

    private String color;

    public Car(String color) {
        this.color = color;
    }

    public boolean equals(Object obj) {
        if(obj==null) return false;
        if (!(obj instanceof Car))
            return false;   
        if (obj == this)
            return true;
        return this.color.equals(((Car) obj).color);
    }

    public static void main(String[] args) {
        Car a1 = new Car("green");
        Car a2 = new Car("red");

        //hashMap stores Car type and its quantity
        HashMap<Car, Integer> m = new HashMap<Car, Integer>();
        m.put(a1, 10);
        m.put(a2, 20);
        System.out.println(m.get(new Car("green")));
    }
}

la voiture verte ne se trouve pas

2. Problème causé par hashCode ()

le problème est causé par la méthode un-overridden hashCode() . Le contrat entre equals() et hashCode() est:

  1. Si deux objets sont égaux, alors ils doivent avoir le même hash code.
  2. si deux objets ont le même code de hachage, ils peuvent être égaux ou non.

    public int hashCode(){  
      return this.color.hashCode(); 
    }
    
2
répondu Neeraj Gahlawat 2017-08-28 06:19:15
Les classes

String et wrapper ont une implémentation différente des méthodes equals() et hashCode() que la classe objet. méthode equals() de la classe Object compare les références des objets, pas le contenu. hashCode () la méthode de la classe objet renvoie un hashCode distinct pour chaque objet, que le contenu soit le même.

cela pose problème lorsque vous utilisez la collection de cartes et que la clé est de type persistant, de type StringBuffer/builder. Car ils n'ont pas contrairement à la classe String, equals() retournera false lorsque vous comparez deux objets différents même si tous les deux ont le même contenu. Le hashMap stockera les mêmes clés de contenu. Stocker les mêmes clés de contenu signifie qu'il viole la règle de Map parce que Map ne permet pas les clés dupliquées du tout. Par conséquent, vous outrepassez les méthodes equals() aussi bien que hashCode () dans votre classe et fournissez l'implémentation (IDE peut générer ces méthodes) de sorte qu'elles fonctionnent de la même façon que les chaînes de caractères. égale() et hashCode() et empêche les mêmes clés de contenu.

vous devez outrepasser la méthode hashCode() avec equals() parce que equals() fonctionne selon hashcode.

de plus, le fait de surcharger la méthode hashCode() avec equals() aide à préserver le contrat equals()-hashCode ():" si deux objets sont égaux, alors ils doivent avoir le même code de hachage."

Quand devez-vous écrire l'implémentation personnalisée pour hashCode()?

comme nous le savons que le travail interne de HashMap est sur le principe du hachage. Il y a certains seaux où les entrées sont stockées. Vous personnalisez l'implémentation hashCode () en fonction de vos besoins afin que les objets de la même catégorie puissent être stockés dans le même index. lorsque vous stockez les valeurs dans la collection de cartes en utilisant la méthode put(k,v) , l'implémentation interne de put () est:

put(k, v){
hash(k);
index=hash & (n-1);
}

Signifie, il génère de l'indice et l'indice est généré à partir du hashcode d'un objet clé particulier. Alors faites que cette méthode génère hashcode selon votre exigence parce que les mêmes entrées hashcode seront stockées dans le même seau ou index.

C'est ça!

2
répondu Arun Raaj 2017-09-02 08:30:26

la raison derrière cette: Lorsque vos champs objet peuvent être nuls, implémenter L'objet.égal peut être une douleur, parce que vous devez vérifier séparément pour null. À L'Aide D'Objets.equal vous permet d'effectuer des vérifications d'égal à égal d'une manière non sensible, sans risquer une NullPointerException. Objects.equal("a", "a"); // returns true Objects.equal(null, "a"); // returns false Objects.equal("a", null); // returns false Objects.equal(null, null); // returns true

1
répondu aman 2015-06-24 05:57:57

hashCode() méthode est utilisée pour obtenir un entier unique pour un objet donné. Cet entier est utilisé pour déterminer l'emplacement du seau, quand cet objet doit être stocké dans quelque HashTable , HashMap comme la structure de données. Par défaut, l'Objet hashCode() méthode retourne et représentation entière de l'adresse mémoire où l'objet est stocké.

la méthode des objets hashCode() est utilisée lorsque nous les insérons dans un HashTable , HashMap ou HashSet . En savoir plus sur HashTables on Wikipedia.org pour référence.

pour insérer n'importe quelle entrée dans la structure de données de carte, nous avons besoin à la fois la clé et la valeur. Si la clé et les valeurs sont des types de données définis par l'utilisateur, le hashCode() de la clé déterminera où stocker l'objet en interne. Quand require de rechercher l'objet à partir de la carte aussi, le code de hachage de la clé sera déterminer où rechercher l'objet.

le code de hachage pointe seulement à un certains "zone" (ou d'une liste, seau, etc) en interne. Puisque différents objets clés peuvent potentiellement avoir le même code de hachage, le code de hachage lui-même n'est pas une garantie que la bonne clé est trouvée. Le HashTable itère alors cette zone (Toutes les clés avec le même code de hachage) et utilise la méthode equals() de la clé pour trouver la bonne clé. Une fois que la bonne clé est trouvée, l'objet stocké pour cette clé est retourné.

donc, comme nous pouvons le voir, une combinaison du hashCode() et Les méthodes equals() sont utilisées pour stocker et rechercher des objets dans un HashTable .

NOTES:

  1. toujours utiliser les mêmes attributs d'un objet pour générer hashCode() et equals() à la fois. Comme dans notre cas, nous avons utilisé l'id de l'employé.

  2. equals() doit être cohérent (si les objets ne sont pas modifiés, alors il doit continuer à retourner la même valeur).

  3. chaque fois que a.equals(b) , puis a.hashCode() doit être identique à b.hashCode() .

  4. si vous outrepassez l'un, vous devez outrepasser l'autre.

http://parameshk.blogspot.in/2014/10/examples-of-comparable-comporator.html

1
répondu Paramesh Korrakuti 2016-03-25 10:33:42

IMHO, c'est selon la règle dit - si deux objets sont égaux alors ils devraient avoir le même hachage, c.-à-d., les objets égaux devraient produire des valeurs de hachage égales.

donné ci-dessus, par défaut égale() dans L'objet est == qui fait la comparaison sur l'adresse, hashCode() renvoie l'adresse en entier(hachage sur l'adresse réelle) qui est à nouveau distinct pour l'objet distinct.

si vous devez utiliser les objets personnalisés dans les collections basées sur le Hash, vous devez outrepasser à la fois égal() et hashCode(), par exemple si je veux maintenir le HashSet des objets employés, si je n'utilise pas de hashCode plus fort et égal je peux supporter de dépasser les deux objets employés différents, cela se produit lorsque j'utilise l'âge comme hashCode(), cependant je devrais utiliser la valeur unique qui peut être L'identifiant de L'employé.

1
répondu Cleonjoys 2017-06-05 16:10:48

pour vous aider à vérifier les objets dupliqués, nous avons besoin d'un custom equals et d'un hashCode.

depuis hashcode retourne toujours un nombre son toujours rapide pour récupérer un objet en utilisant un nombre plutôt qu'une clé alphabétique. comment ça va se passer? supposons que nous avons créé un nouvel objet en passant une valeur qui est déjà disponible dans un autre objet. Maintenant, le nouvel objet retournera la même valeur de hachage que celle d'un autre objet parce que la valeur transmise est la même. Lorsque la même valeur de hachage est retournée, JVM ira à la même adresse de mémoire à chaque fois et si dans le cas où il y a plus d'un objets présents pour la même valeur de hachage, il utilisera la méthode equals() pour identifier l'objet correct.

1
répondu Tavash 2018-04-19 02:27:15

quand vous voulez stocker et récupérer votre objet personnalisé comme une clé dans la carte, alors vous devez toujours outrepasser égal et hashCode dans votre objet personnalisé . Par exemple:

Person p1 = new Person("A",23);
Person p2 = new Person("A",23);
HashMap map = new HashMap();
map.put(p1,"value 1");
map.put(p2,"value 2");

ici p1 & p2 considérera comme un seul objet et map taille sera seulement 1 parce qu'ils sont égaux.

0
répondu Ambrish Rajput 2018-07-16 14:23:56
public class Employee {

    private int empId;
    private String empName;

    public Employee(int empId, String empName) {
        super();
        this.empId = empId;
        this.empName = empName;
    }

    public int getEmpId() {
        return empId;
    }

    public void setEmpId(int empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    @Override
    public String toString() {
        return "Employee [empId=" + empId + ", empName=" + empName + "]";
    }

    @Override
    public int hashCode() {
        return empId + empName.hashCode();
    }

    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }
        if (!(this instanceof Employee)) {
            return false;
        }
        Employee emp = (Employee) obj;
        return this.getEmpId() == emp.getEmpId() && this.getEmpName().equals(emp.getEmpName());
    }

}

Classe D'Essai

public class Test {

    public static void main(String[] args) {
        Employee emp1 = new Employee(101,"Manash");
        Employee emp2 = new Employee(101,"Manash");
        Employee emp3 = new Employee(103,"Ranjan");
        System.out.println(emp1.hashCode());
        System.out.println(emp2.hashCode());
        System.out.println(emp1.equals(emp2));
        System.out.println(emp1.equals(emp3));
    }

}

dans la classe D'objet égale (Object obj) est utilisé pour comparer la compar Sion d'adresse c'est pourquoi quand dans la classe de Test si vous comparez deux objets alors égale méthode donnant false mais quand nous outrepassons hashcode () le Il peut comparer le contenu et donner le bon résultat.

0
répondu Manash Ranjan Dakua 2018-07-17 11:37:53

les deux méthodes sont définies dans la classe objet. Et les deux sont dans leur mise en œuvre la plus simple. Ainsi, lorsque vous avez besoin d'ajouter plus d'implémentation à ces méthodes, alors vous avez le contournement dans votre classe.

pour Ex: equals() la méthode dans l'objet ne vérifie son égalité que sur la référence. Donc si vous avez besoin de comparer son état aussi bien alors vous pouvez annuler cela comme il est fait dans la classe String.

-1
répondu GuruKulki 2017-08-22 11:29:28

Bah - "il est nécessaire de redéfinir hashCode() dans chaque classe qui remplace equals()."

[tiré de Effective Java, de Joshua Bloch?]

N'est-ce pas la mauvaise direction? La suppression du hashCode implique probablement que vous écrivez une classe de hachage-clé, mais la suppression des égaux n'implique certainement pas. Il y a beaucoup de classes qui ne sont pas utilisées comme des clés de hachage, mais qui veulent une méthode de test d'égalité logique pour une autre raison. Si vous choisissez "égal" pour cela, vous pouvez alors être mandaté pour écrire une implémentation de hashCode par une application trop zélée de cette règle. Tout ce qui est fait est d'ajouter du code non testé dans la base de code, un mal attendant de tromper quelqu'un dans le futur. En outre, le code d'écriture dont vous n'avez pas besoin est anti-agile. C'est tout simplement faux (et un ide généré un sera probablement incompatible avec vos égaux fabriqués à la main).

sûrement ils auraient dû exiger une Interface sur les objets écrits pour être utilisés comme clés? Quoi qu'il en soit, Object n'aurait jamais dû fournir le hashCode par défaut() et égal() imho. Il a probablement encouragé beaucoup de collections de hash cassées.

mais de toute façon, je pense que la "règle" est écrite de l'arrière vers l'avant. En attendant, je vais continuer à éviter d'utiliser "égaux" pour les méthodes de test d'égalité : - (

-4
répondu Alan Dobbie 2016-02-19 18:00:16