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 :

Contains ne fonctionne pas sur un HashSet


Sujet :

Langage Java

  1. #1
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut Contains ne fonctionne pas sur un HashSet
    Bonjour,

    J'ai un léger problème avec un HashSet. Voici un bout de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Set<Couple> set = new HashSet<Couple>();
    Couple c = new Couple(v1, v2);
    Couple c2 = new Couple(v1, v2);
    set.add(c);
    System.out.println(set.contains(c2)); // false ??
    System.out.println(c2.equals(c)); // true
    C'est un peu bizarre, non ? Certes c et c2 ne représentent pas le même objet mais la doc précise que c'est le critère c2.equals(c) qui est utilisé pour les méthodes contains, remove, etc...

    Bref, je suis un peu dans le flou là. A noter que si je remplace les Set par des List, ça fonctionne normalement.

    Merci de votre aide.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    vraissemblablement, votre classe Couple ne respecte pas les spécifications dans son implémentation de la méthode equals et hashcode. Tout est précisé dans la javadoc. En l'occurence ici, c1.hashcode()!=c2.hashcode()

  3. #3
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    En effet, ça fonctionne si je redéfinis la méthode hashCode() mais j'ai quand même du mal à comprendre le pourquoi du comment.

    Dans la doc de l'interface Set, je lis :

    Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).
    Hors, cette condition est bien vérifiée dans le bout de code que j'ai posté dans le premier message. Je cherche peut-être au mauvais endroit.

  4. #4
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Ok, en faisant des test, je crois comprendre que contains() commence par vérifier que les hashCode sont égaux avant d'utiliser la méthode equals() mais ça ne correspond pas à ce que je lis dans la doc.

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ca correspond tout a fait. hashset se base sur equals, et la doc de equals dit que si vous redéfinissez equals, vous devez redéfinir hashcode aussi. Bref, la doc est explicite sur tous les points.

    En l'occurence, comme son nom l'indique, hashet distribue les donnée sur une hashtable en fonction de leur hash. Donc si vous ne redefinissez pas le hash correctement....

  6. #6
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Avant tout, merci d'avoir pris le temps de me répondre.

    Justement, la doc précise que la méthode contains() se base sur equals() mais ne fait en aucun cas référence à la "subtilité" au sujet du hashCode().

    Cela dit, on va pas non plus polémiquer non plus pendant 107 ans sur la clarté de la doc. J'ai compris d'où venait le problème, je vais mettre ce thread comme étant résolu.

    Et merci encore.

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Indicates whether some other object is "equal to" this one.

    The equals method implements an equivalence relation on non-null object references:

    * It is reflexive: for any non-null reference value x, x.equals(x) should return true.
    * It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
    * It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
    * It is consistent: for any non-null 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 objects is modified.
    * For any non-null reference value x, x.equals(null) should return false.

    The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

    Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
    Si on devait mentionner le lien entre equals et hashcode pour toutes les classes java qui utilisent la méthode equals, la javadoc serait encore plus lourde à lire Le fonctionnement de ces deux méthode est supposé faire partie du b-a-ba du programmeur et fait partie des Java language specifications

  8. #8
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Sans doute. Mais bon, je suis pas programmeur pro ou quoi que ce soit et le truc sur le hashcode, c'est pas ce qu'on apprend en premier quand on apprend le java sur des sites, dans des bouquins ou autre.

    Quoi qu'il en soit, je dit simplement qu'une doc qui dit ça au sujet de la méthode contains() est une doc fausse :

    Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

  9. #9
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    on peut tergiverser pendant des heures, mais elle est vraie :p

  10. #10
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    S'il était écrit cela, ça serait vrai :

    Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : (o.hashCode() == e.hashCode() && o.equals(e)).

    Je vois pas en quoi il y aurait matière à tergiverser là-dessus. D'ailleurs, écrit comme je l'ai fait ci-dessus, on peut pas dire que ça prenne beaucoup plus de place.

  11. #11
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    le problème n'est pas dans votre utilisation de contains (qui correspond à la doc) mais dans votre classe Couple, qui n'a rien à voir avec hashset, et dont la méthode equals était érronnée

    Si vous aviez ecrit une classe couple telle que c1.equals(c2) == true, et c2.equals(c1)==false, quel aurait du être le comportement de hashset? Il est normal que hashset suppose que votre methode equals se comporte telle qu'elle doit se comporter suivant sa doc, je vois pas de nécessité de reporter ça partout

  12. #12
    Membre averti
    Inscrit en
    Janvier 2009
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Janvier 2009
    Messages : 12
    Par défaut
    Pour le coup, je suis d'accord avec vous. Si on suppose que o.equals(e) implique l'égalité des hash, ça n'est plus la peine de l'écrire comme je le disais dans le post précédent. Disons que j'aurais apprécié que la doc fasse un rappel de cette spécification.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Contains ne fonctionne pas sur un string !
    Par Ceubex dans le forum Langage
    Réponses: 2
    Dernier message: 06/03/2014, 10h53
  2. Réponses: 4
    Dernier message: 03/04/2006, 08h50
  3. Réponses: 7
    Dernier message: 10/02/2006, 18h00
  4. TXMLDocument, ne fonctionne pas sur tous les PC
    Par Neilos dans le forum C++Builder
    Réponses: 4
    Dernier message: 05/10/2005, 22h33
  5. Code qui ne fonctionne pas sur Mac
    Par malbaladejo dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 14/01/2005, 11h08

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