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 :

[Collections] Problème de clés pour les Maps.


Sujet :

Collection et Stream Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut [Collections] Problème de clés pour les Maps.
    Rebonjour,

    Cette fois ci le probleme vient de l utilisation des cle dans une Map.

    J utilise un TreeMap pour stocké des objets et je dois a des instant precis recuperer l objet qui a la plus petite clé.

    Pour moi la cle est un objet Couple qui a comme champs 2 entiers (disons a et b).
    Evidement j ai du implementer la methode compareTo de l'interface Comparable.

    le seul probleme est que lors que je cree 2 objet Couple avec les meme entiers et que je les utilise comme clé, je n ai pas acces au meme donnees dans ma TreeMap.

    un petit exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Couple c1 = new Couple (1,2);
    Couple c2 = new Couple(1,2);
    Map map = new TreeMap();
     
    map.put(c1, "TOTO");
    System.out.println(map.get(c1) == null);
    System.out.println(map.get(c2) == null);
    Le resultat est
    false
    true


    Ce probleme bien du fait que ce soit 2 objet distincts a mon avis. Or lorsqu on cree 2 String indentique ca fonctionne (malheureusement je ne peut pas utiliser de String pour ma cle).
    C est assez embetant pour mon programme. Si quelquun a une dee pour contrer ce probleme.
    Merci.

  2. #2
    Expert confirmé
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Points : 4 166
    Points
    4 166
    Par défaut
    Tu as oublié d'ajouter ta clé c2 à ta TreeMap

    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    Non justement.

    Normalement c1 et c2 sont identique, enfin egaux. J aurais pense que le resultat aurait ete :
    false
    flase

    Par exemple si nous prenons comme cle un objet String :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    String s1 = "aa";
    String s2 = "aa";
    Map map = new TreeMap();
     
    map.put(s1, "TOTO");
    System.out.println(map.get(s1) == null);
    System.out.println(map.get(s2) == null);
    Nous aurons comme resultat:
    false
    false


    J aimerai bien avoir le meme resultat en utilisant des Objets couple comme cle et non des string.

    Le probleme , comme je l ai dit dans mon premier post, est que je ne peux pas utiliser des String car je dois recuprer la plus petite cle (donc le plus petite objet Couple).

  4. #4
    Expert confirmé
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Points : 4 166
    Points
    4 166
    Par défaut
    Probablement que ta classe Couple doit implémenter Comparable (CF autre topic).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public class Couple implements Comparable {
     
      private int key1;
      private int key2;
     
      public int compareTo(Object o) {
     
          ......
     
      }
     
    }
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    Ma classe Couple (comme je l ai dit dans mon premier post) implement l interface comparable.

  6. #6
    Expert confirmé
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Points : 4 166
    Points
    4 166
    Par défaut
    Donnes le code que tu as mis dans la méthode compareTO, à tout hasard. Je suis persuadé que cela vient de la comparaison de tes objets Couple.
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2005
    Messages : 22
    Points : 17
    Points
    17
    Par défaut
    ça serait pas plutôt la méthode equals() qui est à redéfinir?

    Puisque ce que fait get c'est comparer des objets:

    More formally, if this map contains a mapping from a key k to a value v such that (key==null ? k==null : key.equals(k)), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)
    C'est dans l'API de get

  8. #8
    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,


    L'interface Comparable permet seulement de conserver les clefs dans un ordre particulier, par exemple lorsque tu parcours les éléments de la liste via keySet() ou entrySet()... [edit] dans une SortedMap seulement !


    Mais le fonctionnement général des Map n'est pas impacté par cela : les éléments sont recherché via leurs hash-code, et les méthodes hashCode() et equals() doivent être cohérente...


    Lorsque tu ajoutes un couple clef/valeur dans une Map (put()), le hashCode() est utilisé pour stocké le couple et y accéder plus rapidement.

    Lorsque tu recherches un élément par sa clef (get()), le hashCode() de l'élément passé en paramètre est utilisé pour retrouver l'objet, et ensuite la méthode equals() est utilisée pour rechercher la bonne clef (plusieurs objets différents peuvent avoir le même hashcode).


    Pourquoi cela ne marche pas si tu n'implémentes pas ces méthodes ? C'est à cause de l'implémentation par défaut de ces méthodes dans la classe Object :
    • hashCode() retourne une valeur différentes pour chaque objet (correspondant à l'adresse mémoire de l'objet sur la JVM de Sun, mais ce n'est pas obligatoire).
    • equals() ne retourne true que s'il s'agit de la même instance de l'objet :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
          public boolean equals(Object obj) {
      		return (this == obj);
          }


    Bien entendu ces méthodes sont correctement implémenté dans les classes qui le neccessite (String, Integer, etc.), mais ce n'est pas le cas pour toi (et c'est pour cela que cela ne fonctionne que lorsque tu utilise la même instance).


    Donc il faut que tu définisses equals() et hashCode() de manière cohérente (si a.equals(b) alors a.hashCode()==b.hashcode(), mais l'inverse n'est pas forcément vrai).

    Dans ton cas cela pourrait donner ceci :
    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
    37
    38
    39
    40
    public final class Couple {
     
    	private final int x,y;
     
    	public Couple(int pX, int pY) {
    		this.x = pX;
    		this.y = pY;
    	}
     
    	/* (non-Javadoc)
    	 * @see java.lang.Object#hashCode()
    	 */
    	@Override
    	public int hashCode() {
    		final int PRIME = 31;
    		int result = 1;
    		result = PRIME * result + x;
    		result = PRIME * result + y;
    		return result;
    	}
     
    	/* (non-Javadoc)
    	 * @see java.lang.Object#equals(java.lang.Object)
    	 */
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		final Couple other = (Couple) obj;
    		if (x != other.x)
    			return false;
    		if (y != other.y)
    			return false;
    		return true;
    	}
    }
    A noter que la version 3.2M5 d'eclipse permet de générer ces deux méthodes selon certains attributs de l'objets (c'est ce que j'ai fait ici).


    Enfin les objets utilisé en clef ne devrait pas être modifiable, car si le hashCode varie le couple peut être "perdu" (toujours dans la liste mais inacc"ssible via un get()).



    J'espère avoir été clair et pas trop rébarbatif

    a++

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    Merci pour a tous pour vos reponse et plus particulierement a adiGuba pour sa reponse tres clair et tres bien documente.
    J vais essayer cela tout de suite.

    Une ptite question pour les metode hashcode et equals, il y a t il une interface a appeler ?

  10. #10
    Expert confirmé
    Avatar de Hephaistos007
    Profil pro
    Enseignant Chercheur
    Inscrit en
    Décembre 2004
    Messages
    2 493
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 493
    Points : 4 166
    Points
    4 166
    Par défaut
    La réponse d'adiGuba a le mérite d'être très claire. C'est logique mais fallait le savoir...

    Une ptite question pour les metode hashcode et equals, il y a t il une interface a appeler ?
    Non, elle sont héritée de la classe Object. Tu dois les redéfinir.
    Il vaut mieux mobiliser son intelligence sur des conneries que mobiliser sa connerie sur des choses intelligentes --- devise SHADOKS

    Kit de survie Android : mon guide pour apprendre à programmer sur Android, mon tutoriel sur les web services et enfin l'outil en ligne pour vous faire gagner du temps - N'oubliez pas de consulter la FAQ Android

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 131
    Points : 114
    Points
    114
    Par défaut
    C est bon ca marche nikel !!!! MERCIIIIIIIIIIII 8)

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 29/07/2010, 12h41
  2. Réponses: 4
    Dernier message: 29/07/2010, 09h50
  3. Réponses: 0
    Dernier message: 11/04/2010, 11h32
  4. Quelles collections pour les Datasource
    Par _Xavier_ dans le forum iReport
    Réponses: 3
    Dernier message: 11/09/2009, 10h34

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