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 :

Objet en clé d'une HashMap


Sujet :

Collection et Stream Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 121
    Par défaut Objet en clé d'une HashMap
    Bonjour à tous,

    J'ai un problème lors de l'utilisation d'une Hashmap. Je défini une classe Position qui me servira comme clé et valeur de la hashmap. Dans cette classe j'ajoute les fonctions equals(Object), hashCode() et equals(Position) (je ne suis pas sûr de l'utilité de cette dernière mais dans le doute je l'ai tout de même mise). Cela me donne la classe suivante :

    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public class Position {
     
    	private int i;
    	private int j;
    	private int k;
     
    	Position (int x, int y, int z){
     
    		i = x;
    		j = y;
    		k = z;
     
    	}
     
    	public int getI(){
    		return i;
    	}
     
    	public int getJ(){
    		return j;
    	}
     
    	public int getK(){
    		return k;
    	}
     
    	public String toString(){
    		return "(" + i  +  "," + j  +  "," + k + ")";
    	}
     
    	public boolean equals(Position p){	
    		boolean result = false;
     
    		if( this.i == p.i && this.j == p.j && this.k == p.k)
    			result = true;
     
    		return result;
     
    	}
     
    	public boolean equals(Object o){
     
    		boolean result = false;
    		Position p = (Position)o;
     
    		if( this.i == p.i && this.j == p.j && this.k == p.k)
    			result = true;
     
    		return result;
    	}
     
    	public int hashcode(){
    		return this.getI()+this.getJ()+this.getK();
    	}
    }
    Je définie ensuite une hashmap de la façon suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HashMap<Position, Position> hm = new HashMap<Position, Position>();
    J'ajoute dans hm un certain nombre de positions (pour l'instant la clé et la valeur de chaque élément sont identiques), exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Position p = new Position(1, 2, 3);
    hm.put(p, p);

    Le problème est que la fonction HashMap.get me renvoi null lorsque je l'utilise de la maniere suivante : hm.get(new Position(1, 2, 3)). De plus la fonction hm.containsValue(new Position(1, 2, 3)) renverra bien true tandis que la fonction hm.containsKey(new Position(1, 2, 3)) me retournera false.

    Si j'affiche le contenu de hm, j'y vois bien appraître le champ : (1,2,3)=(1,2,3).

    Je ne comprend pas pourquoi les fonctions containsKey et get de HashMap ne me renvoient pas ce que je veux. Au débugage il semble que les fonctions hashcode et equals ne sont pas appelées lors des appels a get et containsKey (tandis que pour la fonction containsValue, il y a bien des appels à la fonction Position.equals(Object)).

    Je dois rater quelque chose mais je ne vois vraiment pas quoi. Auriez-vous une petite idée ?

    N'hésitez pas à me demander plus détails si besoin. Merci d'avance !

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 121
    Par défaut
    hashCode

  3. #3
    Membre Expert
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Par défaut
    Concernant ton probleme, tu l'as compris, c'est hashCode (avec majuscule). Au passage, j'ajouterais qu'il est toujours bien d'utiliser l'annotation @Override. Ainsi, tu l'aurais vu directement

    Citation Envoyé par SAKDOSS Voir le message
    equals(Position) (je ne suis pas sûr de l'utilité de cette dernière mais dans le doute je l'ai tout de même mise).
    Cette fonction fait la meme chose que equals(Object). Elle n'est donc pas necessaire. Par contre, equals(Object) peut etre appelée avec n'importe quel type d'objet. Il est donc prefereable de faire (pour eviter les exceptions de Cast) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public boolean equals(Object o){
     
    		boolean result = false;
                    if(o instanceof Position) {
    		Position p = (Position)o;
     
    		   if( this.i == p.i && this.j == p.j && this.k == p.k)
    			result = true;
                    }
    		return result;
    	}

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


    Si tu es en Java 5 ou plus, tu peux utiliser l'annotation @Override devant les méthodes que tu redéfinis. Cela permet au compilateur de te générer une erreur en cas d'oubli de ce type


    Au passage évites le doublon equals(Position) et equals(Object). C'est inutile et potentiellement source d'erreur.


    De même ton equals() n'est pas correct, car il doit normalement gérer les valeurs nulles sans provoquer d'exception.
    Bref ton equals() devrait plutôt ressembler à cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    	@Override
    	public boolean equals(Object o){
    		// petite optimisation pour la comparaison avec soit-même
    		if (this==o)
    			return true;
    		if (o instanceof Position) {
    			Position p = (Position)o;
     
    			return this.i == p.i 
    				&& this.j == p.j 
    				&& this.k == p.k;
    		}
    		return false;
    	}
    Quand à ton hashCode(), il est trop simple et cela implique trop de collisions. C'est à dire qu'il y a beaucoup d'objets différents qui ont le même hashCode...
    Par exemple les positions (2,0,0), (0,2,0), (0,0,2), (1,1,0), (1,0,1), (0,1,1) ont toute le même hashCode (2 en l'occurrence).

    C'est "problématique" car le hash de la Map ne sera pas très performant du coup.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public int hashCode() {
        int result = 7;
        final int multiplier = 17;
     
        result = multiplier*result + this.i;
        result = multiplier*result + this.j;
        result = multiplier*result + this.k;
     
        return result;
    }
    Un autre moyen simple étant d'utiliser la méthode Arrays.hashCode() pour cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public int hashCode() {
        return Arrays.hashCode(new int[]{ this.i, this.j, this.k});
    }

    Plus d'info dans la FAQ :
    Pourquoi et comment redéfinir la méthode equals() ?
    Pourquoi et comment redéfinir la méthode hashCode() ?

    a++

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 121
    Par défaut
    Merci pour vos reponses. Oui effectivement le mot cle @Override est bien pratique (c'est d'ailleurs grace a lui que j'ai localise l'erreur).

    Effectivement pour le hashCode. Je vais le modifier !

  6. #6
    Nouveau candidat au Club
    Femme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2013
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Autriche

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2013
    Messages : 2
    Par défaut
    Merci pour vos reponses

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

Discussions similaires

  1. Itération sur une HashMap d'objets
    Par spottt dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 08/12/2011, 18h11
  2. [Struts] [HashMap] passage d'un bean dans une HashMap
    Par cosmos38240 dans le forum Struts 1
    Réponses: 4
    Dernier message: 29/09/2005, 16h05
  3. [STRUTS] Itérer sur une HashMap
    Par s.grenet dans le forum Struts 1
    Réponses: 5
    Dernier message: 06/04/2005, 13h26
  4. Cherche un objet un peu comme une TStringList
    Par Desraux dans le forum Langage
    Réponses: 6
    Dernier message: 27/07/2004, 14h04
  5. [débutant] cherche a copier une HashMap
    Par mathieublanc13 dans le forum Collection et Stream
    Réponses: 3
    Dernier message: 09/05/2004, 14h33

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