IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

hashcode et ==


Sujet :

Langage Java

  1. #1
    Futur Membre du Club
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Points : 5
    Points
    5
    Par défaut hashcode et ==
    Bonjour à tous,

    J'ai voulu utiliser l'interface Comparable dans mon code afin d'identifier et de classer des objets dans un TreeSet.
    Les premières lignes de mon implémentation de compareTo(Object o) sont:
    if ( this == o) {
    return 0;
    } else ... <code donnant un entier>

    Ma classe est dans un environnement multithread, a tourné pendant des semaines sans soucis. Puis un beau jour, le programme a remonté une erreur assez bizarre me laissant supposer que j'avais 2 fois la même instance dans mon TreeSet...

    Après un traquage assez hardu (multithread, héritage, environnement Web, plein de classe) et ce bug qui apparaît/disparaît... je suis arrivé à la conclusion que c'était mon test this==o qui ne renvoyait pas true bien que this et o soit la même instance.
    J'ai notamment utilisé hashcode() pour vérifier mes suppositions et cela a régler mon bug:
    if ( this.hashCode() == o.hashCode()) {
    return 0;
    } else if ...

    Ceci renvoie toujours true quand this et o sont la même instance alors que le == ne le faisait pas toujours.

    Quelqu'un sait-il ce qui se cache derrière == ? est-ce equals ? un code natif inconnu ?
    Est-il normal qu'il ne renvoie pas toujours true en multithread ?

    Ai-je bien fait de le remplacer par hashcode() ?


    Pour info, j'ai quelques blocs static susceptibles de modifier mes instances Comparable... cela peut influer sur equals() à ma connaissance.

  2. #2
    Membre chevronné
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Points : 1 958
    Points
    1 958
    Par défaut
    L'opérateur '==' effectue une comparaison sur les adresses des objets alors que la méthode equals() sert à vérifier si deux objets on un contenu identique ( dans le contexte ).
    Personnellement, je n'aurais pas utilisé la méthode hashcode() mais j'aurais surchargé les méthodes equals() et compareTo() de l'objet pour - au final - me servir de la méthode equals().

  3. #3
    Futur Membre du Club
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    L'opérateur '==' effectue une comparaison sur les adresses des objets alors que la méthode equals() sert à vérifier si deux objets on un contenu identique ( dans le contexte ).
    C'est pour ça que le comportement que j'ai m'étonne: si == vérifie les adresses, ne devrais-je pas avoir un comportement stable ?
    car hashcode() renvoie l'équivalent de l'adresse à ma connaissance.

    Info supplémentaire, j'ai testé mon code sur JDK 1.3 et 1.5, et le bug apparaît sur les 2 plateformes. Ce n'est donc pas un changement de spec de JVM qui provoque ce problème.

    Personnellement, je n'aurais pas utilisé la méthode hashcode() mais j'aurais surchargé les méthodes equals() et compareTo() de l'objet pour - au final - me servir de la méthode equals().
    Que mettre dans equals() ? pas this == o car c'est ce qu'il est fait par défaut dans equals(). Je peux y mettre this.hashcode() == o.hashcode() mais je ne vois pas ce que cela apporterait mis à part un code un peu plus propre...

  4. #4
    Membre chevronné
    Profil pro
    Fabrication GED
    Inscrit en
    Octobre 2005
    Messages
    1 405
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Fabrication GED

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 405
    Points : 1 958
    Points
    1 958
    Par défaut
    Pour moi : non hashcode ne retourne pas d'adresse mais un identifiant unique qui peut être utilisé pour distinguer deux objets dont la méthode equals() retournerai true ( javadoc méthode hashcode de la classe java.lang.Object ). Je m'explique :
    Admettant que tu ai une classe "MaClasse" contenant deux attributs "att1" et "att2" de type String.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class MaClasse{
       String att1;
       String att2;
       public boolean equals(Object o){
          MaClasse mc=(MaClasse)o;
          return mc.att1.equals(this.att1)&&mc.att2.equals(this.att2);
    }
    tu remarqueras que dans mon code je compare les deux attributs pour vérifier l'égalité.
    La doc dit que si deux objets sont égaux ( méthode equals ), alors le hashcode devra être le meme pour ces deux objets.
    Elle dit egalement qui si ces objets sont inégaux ( methode equals ), alors le hashcode pour quand-même etre identique pour les deux objets.
    Concretement on pourrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public int hashCode(){
       return this.att1.hashCode();
    }
    L'intérêt de tous est que l'on peut avoir plusieur "niveaux" d'égalité en fonction du contexte.

    Pour l'opérateur '==' il s'agit de comparaison de référence : si deux objets de même classe sont créés dand deux "new" différents, alors cet opérateur retournera toujours faux ( dans notre exemple aussi même si les deux attributs ont une valeur identique : o1.equals(o2) ).

    En espérant avoir été clair.

  5. #5
    Futur Membre du Club
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Points : 5
    Points
    5
    Par défaut
    c'est tout à fait clair.

    Et je suis d'accord avec ce que tu dis

    Pour l'opérateur '==' il s'agit de comparaison de référence
    Donc quand je fais "this == o" et que j'ai bien à faire aux 2 mêmes instances, ne devrais-je pas avoir toujours true ? là est mon problème.

    Il a fallu que j'utilise hashcode() (non surchargé) pour que ça marche !

    Mais je crois avoir trouvé à l'instant la réponse dans la javadoc de Object.equals() qui équivaut à ==. Il y est indiqué:
    It is consistent: for any reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified.
    C'est la fin qui me préoccupe, que je traduirais par "en supposant qu'aucune information utilisée par les comparaisons de equals() ne change". Vu que equals() équivaut à == dans Object, == réponds à ces critères...
    Donc si les attributs de ma référence changent pendant la comparaison, il est normal que == ne ramène pas true.
    Mais je trouve ça quand même bizarre... == n'est pas atomique ? autre erreur...

Discussions similaires

  1. [Optim Code]equals and hashCode are not paired
    Par anitshka dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 15/09/2006, 23h25
  2. [debutant] hashcode et sérialisation
    Par money mark dans le forum Langage
    Réponses: 5
    Dernier message: 11/04/2006, 13h18
  3. Réponses: 5
    Dernier message: 08/12/2005, 22h40
  4. HashCode avec lettres accentuées...
    Par Kineas dans le forum C++
    Réponses: 4
    Dernier message: 08/04/2005, 10h54
  5. [Algo]methode hashcode
    Par mammou dans le forum Langage
    Réponses: 7
    Dernier message: 19/05/2004, 14h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo