Publié le 11 Octobre 2010

En java lorsqu'on effectue une methode get() sur une map ou contains sur un list. Il arrive que bizarrement ça ne marche pas toujours. 

 

Par exemple lorsqu'on utilise une Hashmap avec des Integer on peut écrire le code suivant :

 

Hashmap<Integer, String> map = new Hashmap<Integer, String>();
map.put(new Integer(3), "trois");
map.put(new Integer(7), "sept");
map.put(new Integer(11), "onze");

 

Jusque là rien d'exceptionnel mais ce qui est intéressant c'est qu'on peut récupérer une entrée de la manière suivante:

 

System.out.println(map.get(new Integer(7)); // affiche "sept"
System.out.println(map.get(new Integer(3)); // affiche "trois"

 

Alors que si j'écris une classe Number par exemple sur le même modèle qu'Integer:

 

public class Number{

   private int nb;

   public Number(int number){
      nb = number;
   }

}

 

 

et que j'utilise une map comme précédemment:

 

Hashmap<Number, String> map = new Hashmap<Number, String>();
map.put(new Number(3), "trois");
map.put(new Number(7), "sept");
map.put(new Number(11), "onze");

 

 

 

 

 

alors je ne peux plus récupérer mes valeurs:

System.out.println(map.get(new Number(7)); // affiche null
System.out.println(map.get(new Number(3)); // affiche null

 

 

 

On peut observer le même comportement avec une List et la méthode contains().

 

En fait tout cela s'explique par le fait que les objets Number sont tous différents. En effet à chaque fois j'ai utilisé une nouvelle instance de Number. Donc les clés de la map et les objets utilisés dans le get ne sont pas les mêmes instances donc ils ne sont pas égaux.

 

Oui mais pourquoi ça marche pour les Integer alors ? Et bien tout simplement parce qu'Integer redefinit certaines méthodes tel que equals() et hashCode(), ce qui permet à la JVM de savoir que deux objets integer sont égaux lorsqu'il représente la même valeur.

 

Pour notre classe Number il suffit de définir une méthode equals et une méthode hashCode pour faire fonctionner le get():

 

public class Number{

   private int nb;

   public Number(int number){
      nb = number;
   }

   public boolean equals(Object obj){
      try{
          Number n = (Number) obj;
          return nb == n.nb;
      }
      catch(Exception e){
         return false;
      }
   }

   public int hashCode(){
      return nb;
   }

}

 

 

 

Il est important de bien redéfinir la méthode hashCode() en plus d'equals(). Car ici la redéfinition d'equals ne suffit pas à obtenir le comportement souhaité.

Voir les commentaires

Rédigé par Bliz

Publié dans #Java

Repost 0