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 :

hashTable problème equals


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé Avatar de totoche
    Inscrit en
    Janvier 2004
    Messages
    1 090
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 090
    Par défaut hashTable problème equals
    Bonjour,
    D'après ce que j'avais compris lorsque la méthode hashCode créer un code identique pour 2 valeurs, c'est la méthode equals qui ajuste la bonne valeur,
    Dans mon test (avec un hashcode volontairement absurde) pour 1clé ayant 2 valeurs je n'ai qu'une valeur qui s'affiche.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    package applihashtable;
    import java.util.*;
    
    public class Roman {
        
        /** Creates a new instance of Roman */
        private String nomO;
        private int noIsbO;
        public Roman(String n, int i) {
            this.nomO = n;
            this.noIsbO = i;
        }
        public void setNomTitre(String n){
            this.nomO = n;
        }
        public void setNoIsbn(int i){
            this.noIsbO = i;
        }    
    
        public String getNomTitre(){
            return(this.nomO);
        }
    //    
        public int hashCode(){
          return (this.nomO.length());
          //Je considère le nb de char du titre comme hashcode (volontairement
          //absurde
       }
        
        public boolean equals(Object obj){
            return (this.noIsbO == ((Roman)obj).noIsbO);
            //Pour des clé identique on teste le numéro ISBN de l'instance en cours
            //que l'on compare au cast de l'objet transmis'
            //Note si les 2 romans ont le même ISBN equal n'en ressort qu'1 !!!'
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
        public static void main(String[] args) {
    Hashtable maTable;
            maTable = new Hashtable();
    
            Roman livre = new Roman("A l'Ouest", 1);  
            maTable.put(livre.hashCode(), livre);
            livre = new Roman("A l'Est..", 2);
            maTable.put(livre.hashCode(), livre);
           
          //A l'ouest ET A L'Est... font avoir la même clé : 9'
    
            for (Enumeration e = maTable.keys(); e.hasMoreElements();){
            livre = (Roman)maTable.get(e.nextElement());
            System.out.println(livre.getNomTitre()); 
           }
    le println ne me renvoi que A l'Est..

    Merci de votre aide

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 132
    Par défaut
    Salut,

    La problème vient du fait que tu ajoutes deux fois la même clefs dans ta hash.
    Lorsque tu fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Roman livre = new Roman("A l'Ouest", 1);  
    maTable.put(livre.hashCode(), livre);
    livre = new Roman("A l'Est..", 2);
    maTable.put(livre.hashCode(), livre);
    c'est comme si tu faisais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    maTable.put(new Integer (9), livre);
    maTable.put(new Integer (9), livre);
    D'ou le fait que tu ne te retrouves qu'avec un seul element dans ta liste
    un moyen simple de corriger le problème est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Roman livre = new Roman("A l'Ouest", 1);  
    maTable.put(livre, livre);
    livre = new Roman("A l'Est..", 2);
    maTable.put(livre, livre);
    En fait la methode hashCode et equals sont automatiquement appellees par la hastable sur les clefs.

  3. #3
    Membre éprouvé Avatar de totoche
    Inscrit en
    Janvier 2004
    Messages
    1 090
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 090
    Par défaut
    Lorsque l'on redéfini la méthode hashCode et malgrès la pertinance de l'algo, il arrive que pour 2 ou N valeurs une seule clé soit génèré, aussi la redéfinition de la méthode equals doit permettre d'identifier dans le "buckets", la valeur correspondant au attributs de l'objet que l'on désire. Mon prob est de savoir récupérer des valeurs diff ayant des clés identiques.

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    J'ai l'impression que tu mélanges le fonctionnement interne d'une HashTable avec la façon de l'utiliser.
    Hashcode te permet de regrouper effectivement plusieurs objets dans le même "bucket" (qu'ils soient égaux ou pas) et c'est equals qui te permet de te renvoyer le bon objet.
    Mais c'est l'implémentation interne, ça n'a rien à voir avec la clef que tu utilises.

    Tu ne peux avoir deux cléfs identiques dans une table, c'est tout.

  5. #5
    Membre éprouvé
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Par défaut
    Salut,

    Essaie en changeant de référence :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    public static void main(String[] args) {
            Hashtable maTable;
            maTable = new Hashtable();
     
            Roman livre = new Roman("A l'Ouest", 1);  
            maTable.put(livre.hashCode(), livre);
            Roman livre2 = new Roman("A l'Est..", 2);
            maTable.put(livre2.hashCode(), livre2);
     
          //A l'ouest ET A L'Est... font avoir la même clé : 9'
     
            for (Enumeration e = maTable.keys(); e.hasMoreElements();){
            livre = (Roman)maTable.get(e.nextElement());
            System.out.println(livre.getNomTitre()); 
    }
    Et vois ce que ca te donne. Je n'ai jamais vérifié mais il est possible (et meme fort propable) qu'en changeant l'objet référencé par livre, tu changes par la même l'objet référencé dans ton hashTable, qui est en fait le même.

    F.

    [edit] : nan en fait nan, c'est juste que tu ajoutes deux fois avec 9, le deuxième put doit te renvoyer null non ?

  6. #6
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,



    equals() sert à différencier deux clef qui ont le même hashcode(). Or ici tu utilises deux clef strictement IDENTIQUE correspondant à l'hashCode.


    Bref il faudrait que tu utilises des instances de Livre en tant que clef, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Hashtable maTable = new Hashtable();
     
    Roman livre = new Roman("A l'Ouest", 1);  
    maTable.put(livre, laBilbiothèque1);
    livre = new Roman("A l'Est..", 2);
    maTable.put(livre=, laBilbiothèque2);

    Mais si tu nous donne l'objectif final de tout cela tu aura surement plus d'info...

    a++

  7. #7
    Membre éprouvé Avatar de totoche
    Inscrit en
    Janvier 2004
    Messages
    1 090
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 090
    Par défaut
    Merci mavina, mais j'ai tjs qu'1 valeur de retourné.

  8. #8
    Membre éprouvé Avatar de totoche
    Inscrit en
    Janvier 2004
    Messages
    1 090
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 090
    Par défaut
    bonjour adiGuba,
    Ma question est de savoir comment fait on pour récupérrer les valeurs ayant une clé identique.

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 132
    Par défaut
    Dsl, je ne t'ai pas bien compris

    Comme l'a dit fr1man
    J'ai l'impression que tu mélanges le fonctionnement interne d'une HashTable avec la façon de l'utiliser.
    Hashcode te permet de regrouper effectivement plusieurs objets dans le même "bucket" (qu'ils soient égaux ou pas) et c'est equals qui te permet de te renvoyer le bon objet.
    Mais c'est l'implémentation interne, ça n'a rien à voir avec la clef que tu utilises.

    Tu ne peux avoir deux cléfs identiques dans une table, c'est tout.
    Par contre il est possible d'implementer ta propre solution.

    Voici un exemple de classe permettant de faire, je pense, ce que tu veux:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    static class MaTable<K,V> {
            Hashtable<K, List<V> > table = new Hashtable<K, List<V>> ();
     
            public MaTable (){            
            }
     
     
            public void put (K key, V value){
                getList (key).add (value);
            }
     
            private List<V> getList (K key){
                List<V> values = table.get (key);
                if (values == null){
                    values = new ArrayList<V> ();
                    table.put(key, values);
                }
     
                return values;
            }
     
     
            public List<V> get (K key){
                return table.get (key);
            }
     
            public Enumeration<K> keys(){
                return table.keys ();
            }
     
        }
    C'est un implementation simpliste mais colle à ton exemple
    et ensuite on l'utilise en faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     MaTable<Integer, Roman> maTable = new MaTable<Integer, Roman>();
     
            Roman livre = new Roman("A l'Ouest", 1);  
            maTable.put(livre.hashCode(), livre);
            livre = new Roman("A l'Est..", 2);
            maTable.put(livre.hashCode(), livre);
     
          //A l'ouest ET A L'Est... font avoir la même clé : 9'
     
            for (Enumeration<Integer> e = maTable.keys(); e.hasMoreElements();){
                List<Roman> livres = maTable.get(e.nextElement());
                for (Roman roman : livres){
                    System.out.println(roman.getNomTitre());
                }            
            }

    une autre solution est d'aller voir les google collections qui font ça à merveille

    http://google-collections.googlecode...e-summary.html

  10. #10
    Membre éprouvé Avatar de totoche
    Inscrit en
    Janvier 2004
    Messages
    1 090
    Détails du profil
    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 090
    Par défaut
    J'ai l'impression que tu mélanges le fonctionnement interne d'une HashTable avec la façon de l'utiliser.
    Hashcode te permet de regrouper effectivement plusieurs objets dans le même "bucket" (qu'ils soient égaux ou pas) et c'est equals qui te permet de te renvoyer le bon objet.
    en re-re-re-relisant fr1man je viens de comprendre non pas que fr1man avait mal rédigé, mais mon cerveau fonctionne au ralenti.
    Je croyais que la méthode hashCode servait à définir la clé.
    Mais fr1man m'a éclairé
    La méthode hashCode trouve sa justification car il est ainsi inutile de tenir un 'registre de clé', surtout lorsque la hashtable comporte plusieurs dizaines-centaines-miliers...de couples clé-objet.
    Merci à tous

  11. #11
    Membre éprouvé
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Par défaut
    Salut,

    La complexité d'accès à une valeur par sa clé dépend d'une fonction appelée hashCode définie dans la clé. Cette fonction est déjà définie dans Object, mais pour optimiser la recherche, la surcharger dans vos propres classes (si la clé est une instance d'une classe de votre création) permet un gain de temps non négligeable. Le principe de cette fonction est simple : elle renvoie un entier. Si les deux objets sont égaux, les valeurs renvoyées par leur fonction respectives sont égales, mais l'inverse n'est pas vrai, ce qui veut dire que si deux objets sont inégaux, leurs hashCode ne sont pas forcément inégaux.
    Généralement, on fait renvoyer à la fonction hashCode() d'un objet la somme des hashCode() des éléments le composant.

    source : http://fmora.developpez.com/tutoriel...oduction/#L4.1

    F.

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

Discussions similaires

  1. [Struts] Problème avec logic:equal
    Par Sniper37 dans le forum Struts 1
    Réponses: 9
    Dernier message: 03/03/2011, 15h32
  2. HashTable : Problème pour récupérer une valeur
    Par Difré91 dans le forum Langage
    Réponses: 5
    Dernier message: 12/02/2011, 01h33
  3. Probléme equals en Jsp
    Par tagada30 dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 29/09/2008, 14h25
  4. Réponses: 5
    Dernier message: 21/09/2006, 09h30
  5. [HashTable] Problème de fonctionnement
    Par RR instinct dans le forum Langage
    Réponses: 8
    Dernier message: 22/06/2006, 14h01

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