Problème avec une HashMap en Java

Problème avec une HashMap en Java - Java - Programmation

Marsh Posté le 10-04-2011 à 18:09:31    

Bonjour,  
J'ai un problème dans mon code (ci-dessous). Je n'arrive pas à faire marcher ma méthode getItemsList. J'ai une classe Item (sans s) et une classe Room qui marchent sans problème.  
La méthode getName() est dans la classe Item.  
En fait, apparemment, mon "while" est toujours false. Je ne sais pas pourquoi. Peut-être que ma méthode addItem() ne marche pas.  
Merci de votre aide  

Code :
  1. import java.util.HashMap;
  2. import java.util.Iterator;
  3. public class Items
  4. {
  5.     private HashMap aItems;
  6.     private Iterator <Item> iterItems;
  7.    
  8.     public Items()
  9.     {
  10.         aItems = new HashMap<Item, Room>();
  11.         iterItems = aItems.values().iterator();
  12.     }
  13.    
  14.     public void addItem(Item vItem, Room vRoom)
  15.     {
  16.         aItems.put(vItem, vRoom); 
  17.     }
  18.    
  19.     public void removeItem(Item vItem)
  20.     {
  21.         aItems.remove(vItem); 
  22.     }
  23.    
  24.     public String getItemsList()
  25.     {
  26.         String vList = "Objet(s) présents dans cette salle : ";
  27.         while(iterItems.hasNext())                          //Il y a un problème ici : toujours false.
  28.         {
  29.             vList = vList + iterItems.next().getName();
  30.         }
  31.         return vList;
  32.     }
  33. }


Reply

Marsh Posté le 10-04-2011 à 18:09:31   

Reply

Marsh Posté le 10-04-2011 à 19:18:53    

Marin2 a écrit :

Bonjour,  
En fait, apparemment, mon "while" est toujours false. Je ne sais pas pourquoi. Peut-être que ma méthode addItem() ne marche pas.  


Ta méthode addItem() est correcte. Ton problème vient du fait qu'un itérateur n'est pas mis à jour lorsqu'un élément est ajouté ou retiré d'une collection.
Essaie de corriger ton code avec cet indice.

Reply

Marsh Posté le 10-04-2011 à 19:24:08    

C'est normal, car tu crées l'itérateur alors que ta map est vide. Pour que cela fonctionne, il faut créer l'itérateur dans la méthode getItemList().
 
Après, il est mieux de faire quelque chose comme ca:

Code :
  1. StringBuilder builder = new StringBuilder("Objet(s) présents dans cette salle : " );
  2. for (Room aRoom : aItems.values()) {
  3.  builder.append(aRoom.getName());
  4. }
  5. return builder.toString()


 
Concaténer des chaînes de caractères dans une boucle for est toujours une mauvaise idée. Les objets StringBuilder (ou String Buffer) sont fait pour.


Message édité par mr simon le 10-04-2011 à 19:24:36
Reply

Marsh Posté le 10-04-2011 à 21:04:28    

Ah, d'accord, merci beaucoup pour votre aide.
 
Autre petite question : j'ai une erreur lors de l’exécution du programme.
 
Après avoir compilé sans problème, je crée d'abord une instance d'Item (appelée par exemple knife), et une instance de Room (par exemple kitchen), et enfin, je lance la méthode kitchen.addItem(knife).
Et là erreur !!! : java.lang.NullPointerException dans la classe Room sur la ligne  :

Code :
  1. aItemList.put(vItem);


 
Voici ma classe Room (ou plutot, les éléments de ma classe Room qui nous intéressent):
 

Code :
  1. import java.util.HashMap;
  2. import java.util.Set;
  3. //import java.util.Iterator;
  4. public class Room
  5. {
  6.     private String description;
  7.     private HashMap<String, Room> exits;
  8.     private String imageName;
  9.     private Item aItem;
  10.    
  11.     private Items aItemList;
  12.    
  13.     public Room(String pDescription, String pImage)
  14.     {
  15.         this.description = pDescription;
  16.         exits = new HashMap<String, Room>();
  17.        
  18.         imageName = pImage;
  19.        
  20.         Items aItemList = new Items();
  21.     }
  22.     public void addItem(Item vItem)
  23.     {
  24.         aItemList.put(vItem);
  25.     }
  26.    
  27.     public void removeItem(Item vItem)
  28.     {
  29.         aItemList.removeItem(vItem);
  30.     }


 
et ma classe Item :

Code :
  1. public class Item
  2. {
  3.     private String aName;
  4.     private String aDescription;
  5.     private int aWeight;
  6.     /**
  7.      * Constructor for objects of class Item
  8.      */
  9.     public Item(final String pName, final String pDescription, final int pWeight)
  10.     {
  11.         aName = pName;
  12.         aDescription = pDescription;
  13.         aWeight = pWeight;
  14.     }
  15.    
  16.     public String getName()
  17.     {
  18.         return aName;
  19.     }
  20.    
  21.     public String getDescription()
  22.     {
  23.         return aDescription;
  24.     }
  25.    
  26.     public int getWeight()
  27.     {
  28.         return aWeight;
  29.     }
  30. }


 
Et enfin, ma classe Items (qui n'est pas la même que celle que je vous ai montré dans le message précédent : la HashMap n'est plus de type "Item - Room", mais de type "String - Item" )
 

Code :
  1. import java.util.HashMap;
  2. public class Items
  3. {
  4.     private HashMap aItems;         //aItems est la liste des items contenus dans une salle
  5.     public Items()
  6.     {
  7.        aItems = new HashMap<String, Item>();
  8.     }
  9.     public void put(Item vItem)
  10.     {
  11.         aItems.put(vItem.getName(), vItem); 
  12.     }
  13.    
  14.     public void removeItem(Item vItem)
  15.     {
  16.         aItems.remove(vItem); 
  17.     }


 
Attention : Item et Items sont différentes ! Il y a un S dans la signature de la deuxième, et ce n'est pas la même classe.


Message édité par Marin2 le 10-04-2011 à 21:06:00
Reply

Marsh Posté le 10-04-2011 à 21:44:24    

1. J'peux dire que tes naming conventions sont ignobles? C'est quoi ces préfixes `p` de partout là [:pingouino dei]
2. Fixe tes generics dans Items
3. Dans le constructeur de Room, tu crées une variable locale aItemList qui shadow la variable de classe. Donc ton aItemList n'est jamais initialisé.


Message édité par masklinn le 10-04-2011 à 21:44:34

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 10-04-2011 à 22:02:25    

Alors, pour le 1., P comme paramètre. Je mets un p devant les paramètres, un a devant les attributs, et un v devant les variables locales (enfin, j'oublie parfois...)
 
Par contre, je comprends pas trop tes réponses. C'est quoi un generic ? Et ça veut dire quoi "shadow" ?
Désolé, ces questions sont peut etre débile, je suis loin d'être un pro en java...

Reply

Marsh Posté le 10-04-2011 à 22:11:23    

Marin2 a écrit :

Alors, pour le 1., P comme paramètre. Je mets un p devant les paramètres, un a devant les attributs, et un v devant les variables locales (enfin, j'oublie parfois...)


Mais... ça sert à rien [:sadnoir]

Marin2 a écrit :

Par contre, je comprends pas trop tes réponses. C'est quoi un generic ?


Les types sur les collections, genre Map<String, Items>. Tu regardes même pas les warnings du compilo?

 

Vas lire http://download.oracle.com/javase/ [...] erics.html

Marin2 a écrit :

Et ça veut dire quoi "shadow" ?


http://en.wikipedia.org/wiki/Variable_shadowing


Message édité par masklinn le 10-04-2011 à 22:11:49

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 12-04-2011 à 02:01:29    

Ok, pour le shadow, c'est reglé. Merci.
 
Par contre, j'arrive pas à régler le problème des generics. Je ne comprends pas où il faut les mettre dans mon programme (sur la signature de la classe, ça empeche le programme de compiler)
 
Enfin, une autre question (désolé, je m'arrete plus, vous m'aidez si bien :) )
 
J'ai rajouté une fonction "regarder" dans mon programme, qui affiche une description des items dans la room (même code qu'à mon dernier message).
 
J'ai ajouté à la classe Items ces 2 méthodes :
 

Code :
  1. public String getItemList()
  2.     { 
  3.         StringBuilder returnString = new StringBuilder("Vous apercevez des objets dans cette salle : " );
  4.         Set<String> keys = aItems.keySet();
  5.        
  6.         for(String itemName : keys)
  7.         {
  8.             returnString.append(itemName).append(", " );
  9.         }
  10.         return returnString.toString();     
  11.     }


 
Cette première méthode marche. Mais je suis un peu perfectionniste, et j'aimerai virer la virgule en trop qu'il y a à la fin de la liste des objets. Je ne maitrise pas assez les méthodes de StringBuilder pour réussir (malgré un bon moment passé à lire la Javadoc). La méthode setCharAt ne marche pas (ou plutot, je n'arrive pas à l'utiliser). Peut etre n'est-ce pas la bonne...
 

Code :
  1. //je reprends la clé (appelé itemName) et je lui trouve sa value dans la HashMap, à laquelle j'associe une méthode getWeight().
  2.     public String getItemDetails()
  3.     { 
  4.         StringBuilder returnString = new StringBuilder("" );
  5.         Set<String> keys = aItems.keySet();
  6.        
  7.         for(String itemName : keys)
  8.         {
  9.             returnString.append(itemName).append(" qui pèse " ).append(aItems.get(itemName).getWeight()).append(" kg. Après les avoir examiné, vous en déduisez que c'est " ).append(aItems.get(itemName).getDescription());
  10.         }
  11.         return returnString.toString();     
  12.     }


 
Ici, ça ne compile même pas. Le compilateur dit qu'il ne trouve pas les méthodes getWeight() et getDescription(), qui sont pourtant bien définies dans la classe Item.
 
Merci de votre aide. J'espère que malgré mes questions incessantes, vous me répondrez quand même. Je vous suis très reconnaissant.

Reply

Marsh Posté le 12-04-2011 à 10:55:35    

Marin2 a écrit :

Ok, pour le shadow, c'est reglé. Merci.

 

Par contre, j'arrive pas à régler le problème des generics. Je ne comprends pas où il faut les mettre dans mon programme (sur la signature de la classe, ça empeche le programme de compiler)


Les specs de generics, ça va sur les conteneurs génériques. Tu as lu le lien que j'ai donné sur le sujet?

Marin2 a écrit :

J'ai rajouté une fonction "regarder" dans mon programme, qui affiche une description des items dans la room (même code qu'à mon dernier message).

 

J'ai ajouté à la classe Items ces 2 méthodes :

 
Code :
  1. public String getItemList()
  2.     { 
  3.         StringBuilder returnString = new StringBuilder("Vous apercevez des objets dans cette salle : " );
  4.         Set<String> keys = aItems.keySet();
  5.        
  6.         for(String itemName : keys)
  7.         {
  8.             returnString.append(itemName).append(", " );
  9.         }
  10.         return returnString.toString();     
  11.     }
 

Cette première méthode marche. Mais je suis un peu perfectionniste, et j'aimerai virer la virgule en trop qu'il y a à la fin de la liste des objets. Je ne maitrise pas assez les méthodes de StringBuilder pour réussir (malgré un bon moment passé à lire la Javadoc). La méthode setCharAt ne marche pas (ou plutot, je n'arrive pas à l'utiliser). Peut etre n'est-ce pas la bonne...


StringBuilder#delete

Marin2 a écrit :


Code :
  1. //je reprends la clé (appelé itemName) et je lui trouve sa value dans la HashMap, à laquelle j'associe une méthode getWeight().
  2.     public String getItemDetails()
  3.     { 
  4.         StringBuilder returnString = new StringBuilder("" );
  5.         Set<String> keys = aItems.keySet();
  6.        
  7.         for(String itemName : keys)
  8.         {
  9.             returnString.append(itemName).append(" qui pèse " ).append(aItems.get(itemName).getWeight()).append(" kg. Après les avoir examiné, vous en déduisez que c'est " ).append(aItems.get(itemName).getDescription());
  10.         }
  11.         return returnString.toString();     
  12.     }
 

Ici, ça ne compile même pas. Le compilateur dit qu'il ne trouve pas les méthodes getWeight() et getDescription(), qui sont pourtant bien définies dans la classe Item.


Je pense qu'il t'en dit un peu plus. Genre qu'il te dit dans quel objet il cherche ces méthodes et ne les trouve pas, et on en revient directement à tes collections mal typées [:dawa]


Message édité par masklinn le 12-04-2011 à 10:59:39

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 12-04-2011 à 16:54:21    

Oui, je l'ai lu. Mais bon, j'ai pas tout compris, ça reste pas mal flou.
Sinon, j'utilise bluej comme logiciel (exigence débile de mon prof, j'ai pas le choix). Ca donne pas beaucoup de détails pour les erreurs de compilation. Donc j'en sais pas plus sur l'absence des méthodes getWeight() et getDescription().
 
Quand j'écris ça dans mon code (dans la classe Items), et que j'enlève mon constructeur, ça ne compile plus (j'ai droit à l'erreur "; expected" ). Je ne comprends pas pourquoi :
 

Code :
  1. private HashMap aItems <String,Item> = new HashMap<String,Item>();


 
Ce n'est pas ça, le conteneur générique ?
 
Et merci pour delete(), pour le Stringbuilder. Ca marche.

Reply

Marsh Posté le 12-04-2011 à 16:54:21   

Reply

Marsh Posté le 12-04-2011 à 17:07:04    

C'est ca qu'il faut ecrire:

Code :
  1. private HashMap<String,Item> aItems  = new HashMap<String,Item>();
  2. // ou encore mieux:
  3. private Map<String,Item> aItems  = new HashMap<String,Item>();


 
Relie le lien de Masklinn ...

Reply

Marsh Posté le 12-04-2011 à 17:27:51    

Marin2 a écrit :

Oui, je l'ai lu. Mais bon, j'ai pas tout compris, ça reste pas mal flou.
Sinon, j'utilise bluej comme logiciel (exigence débile de mon prof, j'ai pas le choix). Ca donne pas beaucoup de détails pour les erreurs de compilation. Donc j'en sais pas plus sur l'absence des méthodes getWeight() et getDescription().


Ça m'étonne, il donnerait moins de détails que le compilateur java (qui en donne déjà pas des masses)?


Message édité par masklinn le 12-04-2011 à 17:27:55

---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 12-04-2011 à 19:08:02    

Ok, un gros merci à tous les deux, c'est vraiment super sympa de votre part. Tous mes problèmes me semblent réglés (jusqu'à la prochaine fois :p ).

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed