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

Collection et Stream Java Discussion :

HashMap containsKey ne fonctionne pas


Sujet :

Collection et Stream Java

  1. #1
    Rédacteur
    Avatar de David55
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Août 2010
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Août 2010
    Messages : 1 542
    Points : 2 808
    Points
    2 808
    Par défaut HashMap containsKey ne fonctionne pas
    Bonjour à tous et à toutes,

    Je possède une HashMap du type: HashMap<Pair<ClassA, ClasseB>, Integer>

    Je l'ai rempli. Maintenant, j'aimerai utiliser la fonction containsKey afin de pouvoir incrémenter l'entier de ma hashMap si la pair existe déjà.

    Donc voici mon code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    HashMap<Pair<ClassA, ClasseB>, Integer> hm = new HashMap<Pair<ClassA, ClasseB>, Integer>();
     
    for (int i = 0; i < size; i++)
    {
    ClasseA a = getInstanceA(i); 
    ClasseB b = getInstanceB(i);
    Pair<ClasseA, ClasseB> key = new Pair<ClasseA, ClasseB>(a,b);
    if (hm.containsKey (key))
    hm.put (key, hm.get (key) + 1);
    else
    hm.put (key, 1);
    }

    Le problème est que containsKey me renvoit toujours faux. J'ai vu sur internet qu'il fallait redéfinir equal et hashcode mais je n'ai aucune idée de comment faire!

    Quelqu'un pourrait m'aider s'il vous plait?

    Merci d'avance.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    http://java.developpez.com/faq/java/...#DIVERS_equals

    J'ajoute que faire preuve de curiosité avec la JavaDoc et regarder les méthodes equals() et hashCode() qui existent déjà, et remonter jusqu'à celles de Object, tout cela donne déjà un aperçu. (Sans doute pas suffisant pour faire quelque chose de maintenable, mais suffisant pour avoir quelque chose qui marche.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre expérimenté Avatar de Ivelios
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2008
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 031
    Points : 1 540
    Points
    1 540
    Par défaut
    J'ai vu sur internet qu'il fallait redéfinir equal et hashcode
    ça parait logique pour equals, je ne connais pas hashcode.

    Pour equals, quelques explications :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (hm.containsKey (key))
    Cette fonction utilise probablement equals pour regarder si key est égal à une des clés de la table.
    Or pour le moment tu n'as pas redéfinie la méthode equals dans la classe Paire donc il prend celle par défaut.
    Donc dans la classe Paire : (je prend des Integer c'est plus simple)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public classe Paire<Integer,Integer>{
     
     
    public boolean equals(Paire paire){
    return paire.getFirstInteger() == this.firstInteger && paire.getLastInteger == this.lastInteger.
    }
    Si les classes utilisées ne sont pas des integers il faut utiliser "equals" au lieu de == et redéfinir equals dans les classes

    Edit : grillé
    Il était une fois [...] Et ils vécurent heureux et eurent beaucoup d'enfants!

  4. #4
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    - Equals : c'est la méthode qui dit à quelle condition 2 objets sont égaux. Concrètement, ça se fait en général avec une implémentation de equals(Object b) qui teste :
    1. D'abord si les 2 objets sont le même objet (test du ==, c'est toujours plus rapide si ça marche que de checker le reste).
    2. On teste que l'objet b est une instance d'une classe qui peut être comparée pour l'égalité à l'instance courante.
    3. Vérification sur les valeurs des identifiants.

    - Hashcode : c'est la méthode de hachage. Concrètement, il faut produire un entier de façon homogène, ce qu'on fait en général en additionnant les valeurs de hachage des objets qui en définissent l'identité, avec des multiplications par des nombres premiers.

    Ce qui est primordial, c'est que deux objets égaux (selon la méthode equals) doivent avoir le même hashcode.

    Imaginons un objet Personne dans une appli de la sécurité sociale : son identifiant unique est son n° de sécu. Dans ce cas, on pourrait faire très simplement :

    [pardon pour le code crado, je fais ça à l'arrache]
    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
     
    public class PersonneSecu {
     
       private Long noSecu;
     
       private String nom; // champ non utilisé dans le hashcode, on n'utilise que l'id
     
       public int hashCode() {
          return (noSecu == null) ? 0 : noSecu.hashCode();
       }
     
       public boolean equals(Object o) {
       if (o == this) return true;
       if (!(o instanceof PersonneSecu)) return false;
       PersonneSecu that = (PersonneSecu) o;
       return (this.noSecu == null) ? (that.noSecu == null) : (this.noSecu.equals(that.noSecu));
       }
     
    }
    Là c'est un id simple, quand il y a plusieurs id, ça donne des choses du genre
    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
     
     
    public int hashCode() {
    int hash = id1.hashCode();
    hash = 17* hash + id2.hashCode();
    return hash;
    }
     
    public boolean equals(Object o) {
    // même genre de début
     
    boolean eq = (this.id1 == null) ? (that.id1 == null) : (this.id1 .equals(that.id1 ));
    if (!eq) return false;
    return (this.id2 == null) ? (that.id2 == null) : (this.id2 .equals(that.id2 ));
    }

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par Ivelios Voir le message
    ça parait logique pour equals, je ne connais pas hashcode.
    HashMap est une HashMap. Une table de hachage. Les objets qu'on met dedans doivent pouvoir produire un nombre qui les représente plus ou moins, un hash, et qui détermine dans quels tiroirs ils sont rangés.

    - Deux objets non-égaux peuvent avoir le même hash, ils seront rangés dans le même tiroir, c'est pas grave. Le principe est d'éviter que les objets aient trop souvent le même hash, mais ce n'est pas dramatique.

    - Deux objets égaux doivent avoir le même hash. Puisqu'ils sont égaux, on doit forcément choisir le même tiroir pour les ranger (et donc où les chercher pour voir s'il sont déjà là.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Rédacteur
    Avatar de David55
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Août 2010
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Août 2010
    Messages : 1 542
    Points : 2 808
    Points
    2 808
    Par défaut
    Merci pour toutes vos réponses!

    Mon problème est bien entendu de redéfinir les fonctions hashCode et equal pour une paire. La classe Pair ne m'appartient pas. Faut il la redéfinir juste pour cela?

    Ceci étant j'ai contourné le problème en créant une classe ClasseAB qui contient Classe A et ClasseB. Comme ca plus besoin de Pair et je peux redéfinir mes fonctions. Je voulais juste savoir s'il y avait un moyen plus simple!


    Mon code :

    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
     
    private class ClasseAB
    	{
    		private ClasseA a;
    		private ClasseB b;
     
    		public ClasseAB (ClasseA a, ClasseB b)
    		{
    			this.a = a;
    			this.b = b;
    		}
     
    		public String toString ()
    		{
    			return a.libelle + " " + b.libelle;
    		}
     
    		public int hashCode () 
    		{
    			return this.toString ().hashCode ();
    		}
     
    		public boolean equals (Object ab)
    		{
    			return (((ClasseAB)ab).a.equals (a) && ((ClasseAB)ab).b.equals (b));
    		}
    	}

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par David55 Voir le message
    Mon problème est bien entendu de redéfinir les fonctions hashCode et equal pour une paire. La classe Pair ne m'appartient pas. Faut il la redéfinir juste pour cela?
    Hélas. Il n'y a pas moyen d'indiquer un autre hasheur ni comparateur à utiliser que ceux des classes des objets insérés.

    Mais bon, Pair est une classe totalement triviale : la preuve, tu l'as plus ou moins refaite toi-même, en, quoi, 10 minutes ?

    Citation Envoyé par David55 Voir le message
    Ceci étant j'ai contourné le problème en créant une classe ClasseAB qui contient Classe A et ClasseB. Comme ca plus besoin de Pair et je peux redéfinir mes fonction. Je voulais juste savoir s'il y avait un moyen plus simple!
    C'est juste un peu plus spécialisé que Pair, il n'y a pas vraiment de différence.

    Hélas, il n'y a guère plus simple. Il existe par-ci par-là des implémentations de Map hachée à clé double, mais rien dans Java de base ni dans les biblis de collections que je connais. Apparemment ça plaît pas.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Rédacteur
    Avatar de David55
    Homme Profil pro
    Ingénieur informatique
    Inscrit en
    Août 2010
    Messages
    1 542
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Août 2010
    Messages : 1 542
    Points : 2 808
    Points
    2 808
    Par défaut
    Merci pour cette réponse! Au moins je suis sure

  9. #9
    Expert éminent sénior
    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
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par David55 Voir le message
    Ceci étant j'ai contourné le problème en créant une classe ClasseAB qui contient Classe A et ClasseB.
    Autant directement faire une classe générique Pair<A,B>


    Au passage ton hashCode est un peu basique, autant utiliser l'exemple de la FAQ ou un builder fait pour...

    Idem pour equals(), qui là est carrément incorrect (il peut remonter des exceptions, ce qui ne devrait pas être le cas).


    a++

  10. #10
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Hélas. Il n'y a pas moyen d'indiquer un autre hasheur ni comparateur à utiliser que ceux des classes des objets insérés.
    J'ai déjà fait ça : une classe spécialisée de HashMap, avec un objet conteneur qui gère son propre hashCode. Pas top, mais quand on a pas le choix pour cause d'interaction avec du code non modifiable et pourri ~~

    Citation Envoyé par adiGuba
    Au passage ton hashCode est un peu basique, autant utiliser l'exemple de la FAQ ou un builder fait pour...

    Idem pour equals(), qui là est carrément incorrect (il peut remonter des exceptions, ce qui ne devrait pas être le cas).
    Et de plus, sauf à imaginer que les méthodes equals des deux classes reposent intégralement sur les libellés, hashCode et equals ne sont pas cohérents.

  11. #11
    Membre éprouvé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    697
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Janvier 2007
    Messages : 697
    Points : 1 241
    Points
    1 241
    Par défaut
    Il n'y a pas justement dans Java 7 des outils pour les générer ? Au pire tu peux utiliser l'API google collection.

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

Discussions similaires

  1. hashMap.get(key) ne fonctionne pas comme je l'attendais ?
    Par francky74 dans le forum Android
    Réponses: 6
    Dernier message: 13/01/2015, 12h07
  2. Réponses: 6
    Dernier message: 27/01/2004, 11h14
  3. UNION qui ne fonctionne pas
    Par r-zo dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/07/2003, 10h04
  4. Un Hint sur un PopupMenu ne fonctionne pas !!??
    Par momox dans le forum C++Builder
    Réponses: 6
    Dernier message: 26/05/2003, 16h48
  5. ca ne fonctionne pas (generateur auto-incrémentant)
    Par tripper.dim dans le forum SQL
    Réponses: 7
    Dernier message: 26/11/2002, 00h10

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