Java hashtable clé à deux éléments
Résolu
c.limero
Messages postés
7
Date d'inscription
Statut
Membre
Dernière intervention
-
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
KX Messages postés 16761 Date d'inscription Statut Modérateur Dernière intervention -
Bonjour,
Je suis en ce moment entrain de travailler sur un projet de programmation à la fac, qui consiste à mettre en réseau des aquariums.
chaque utilisateur pouvant créer plusieurs objets, chaque objet a un champ userID et itemID afin de pouvoir etre repéré facilement.
dans mon serveur, pour stocker ces objets, j'ai souhaité utiliser une table de hachage, parce que je pensais que c'était super pratique de pouvoir accéder directement à un objet par une clé qui serait représentée par ses deux ID.
voila mon code :
mais voila, je me suis rendu compte qu'au final, ce qui servait de clé ce n'était pas le contenu de ma clé, mais son adresse, et résultat ma table ne contient qu'un élément.
Je n'ai pas réussit à trouver dans la doc ni sur google comment faire pour avoir une clé à partir de deux entiers, avez vous une idée ?
meme si je mets le " Integer cle[] =new Integer[2];" à l'intérieur des boucles, je ne vais pas pouvoir me servir de ma table de hachage parce que je ne pourrai pas repérer un item par ses IDs
Je suis en ce moment entrain de travailler sur un projet de programmation à la fac, qui consiste à mettre en réseau des aquariums.
chaque utilisateur pouvant créer plusieurs objets, chaque objet a un champ userID et itemID afin de pouvoir etre repéré facilement.
dans mon serveur, pour stocker ces objets, j'ai souhaité utiliser une table de hachage, parce que je pensais que c'était super pratique de pouvoir accéder directement à un objet par une clé qui serait représentée par ses deux ID.
voila mon code :
public static void createItems(){ int i; //à garder pour creer des IDs différentes StoneFactory sf = new StoneFactory(); SeaweedFactory swf = new SeaweedFactory(); Integer cle[] =new Integer[2]; //contient l'userID et l'itemID for (i=0 ; i< NB_STONE ; i++){ Stone s = sf.newItems(i, myID); sf.sink(items.values(), s); //pour éviter que deux objets se superposent cle[0]=i; cle[1] = myID; //ID du serveur items.put(cle, s); } for (int j= i ; j-i< NB_SEAWEED ; j++){ //idem pour les algues Seaweed sw = swf.newItems(j, myID); swf.sink(items.values(), sw); cle[0]=j; cle[1] = myID; items.put(cle, sw); } }
mais voila, je me suis rendu compte qu'au final, ce qui servait de clé ce n'était pas le contenu de ma clé, mais son adresse, et résultat ma table ne contient qu'un élément.
Je n'ai pas réussit à trouver dans la doc ni sur google comment faire pour avoir une clé à partir de deux entiers, avez vous une idée ?
meme si je mets le " Integer cle[] =new Integer[2];" à l'intérieur des boucles, je ne vais pas pouvoir me servir de ma table de hachage parce que je ne pourrai pas repérer un item par ses IDs
A voir également:
- Java hashtable clé à deux éléments
- Waptrick java football - Télécharger - Jeux vidéo
- Jeux java itel - Télécharger - Jeux vidéo
- Clé usb non détectée - Guide
- Clé windows 8 - Guide
- Formater clé usb - Guide
5 réponses
Tu pourrais faire deux HashMap<Integer,Stone> la première avec les userID comme clé, la deuxième avec les itemID. À moins que tes entiers soient très différent (aucun userID commun avec les itemID) auquel cas tu peux carrément tout mettre dans la même map.
Remarque : Les objets Stone ne seront pas copiés puisqu'on ne manipule que les références, ça reste donc assez souple en mémoire.
Tu peux bien sûr te créer une petite classe pour manipuler tes map et être sûr d'être cohérent dans la manipulation de tes données.
Remarque : Les objets Stone ne seront pas copiés puisqu'on ne manipule que les références, ça reste donc assez souple en mémoire.
Tu peux bien sûr te créer une petite classe pour manipuler tes map et être sûr d'être cohérent dans la manipulation de tes données.
class doubleMap { private final HashMap<Integer,Stone> mapUser; private final HashMap<Integer,Stone> mapItem; public boolean put(Integer userID,Integer itemID,Stone s) { return mapUser.add(userID,s) && mapItem.add(itemID,s); } public Stone getUser(Integer userID) { return mapUser.get(userID); } public Stone getItem(Integer itemID) { return mapItem.get(itemID); } }
Bonsoir KX,
Si un meme utilisateur ajoute deux pierres, elles auront un itemID différent, mais le meme userID. Inversement, si deux utilisateurs ajoutent une pierre, elles auront un userID différent, mais rien ne garanti qu'elles n'auront pas le meme itemID.
Je ne peux donc pas envisager cette solution :/
Si un meme utilisateur ajoute deux pierres, elles auront un itemID différent, mais le meme userID. Inversement, si deux utilisateurs ajoutent une pierre, elles auront un userID différent, mais rien ne garanti qu'elles n'auront pas le meme itemID.
Je ne peux donc pas envisager cette solution :/
Bon j'avoue que je n'avais pas forcément bien compris le problème ^^
Alors peut-être que tu peux utiliser une HashMap<Identifiant,Stone> avec :
Alors peut-être que tu peux utiliser une HashMap<Identifiant,Stone> avec :
class Identifiant { private final int user; private final int item; public Identifiant(int userID,int itemID) { user=userID; item=itemID; } @Override public boolean equals(Object obj) { if (obj instanceof Identifiant) { Identifiant id = (Identifiant) obj; return id.user==user && id.item==item; } else return false; } @Override public int hashCode() { return user*item; // par exemple } }
J'ai bien pensé à un truc comme ça, mais je ne vois pas de hashCode permettant de distinguer à coup sur un couple.
Par exemple là, la clé (2,1) est la meme que la clé (1,2), ce que je en veux pas.
C'est d'autant plus difficile que l'itemID est donné par le client. et ce n'est pas forcément moi qui code le client, les projets de tous ceux de ma promo doivent pouvoir se connecter à mon serveur, donc mon hashCode doit etre sûr
Par exemple là, la clé (2,1) est la meme que la clé (1,2), ce que je en veux pas.
C'est d'autant plus difficile que l'itemID est donné par le client. et ce n'est pas forcément moi qui code le client, les projets de tous ceux de ma promo doivent pouvoir se connecter à mon serveur, donc mon hashCode doit etre sûr
Une classe Couple c'est exactement ce que j'ai fait tout à l'heure...
Si le hashCode est identique pour deux identifiants différents la méthode equals est appelé, donc ce n'est pas un problème pour (1,2) et (2,1), parce qu'après on aura 1==2 && 2==1 qui donnera false.
Du coup les deux identifiants seront différents tu n'as pas à t'en faire pour ça.
L'intérêt du hashCode est de comparer deux identifiants de manière plus rapide que l'appel de equals. En fait user*item comme je l'ai fait tout à l'heure c'est trop compliqué pour être vraiment intéressant. il vaudrait mieux faire un hashCode qui retourne juste user (ou item) comme ça si les deux users sont identiques on appelle equals pour comparer user ET item (donc on aura fait 3 comparaisons), mais en général on les deux users sont différents avec le hashCode on n'aura comparé que l'user (et donc fait 1 seule comparaison). En moyenne on fait donc moins de 2 comparaisons c'est plus rapide. Après à toi de voir s'il est plus intéressant de mettre user ou item pour qu'on appelle le moins souvent equals. Mais tout ceci ce n'est que de l'optimisation, ça ne change rien au fait que de toute façon le hashCode est complété par equals.
Si le hashCode est identique pour deux identifiants différents la méthode equals est appelé, donc ce n'est pas un problème pour (1,2) et (2,1), parce qu'après on aura 1==2 && 2==1 qui donnera false.
Du coup les deux identifiants seront différents tu n'as pas à t'en faire pour ça.
L'intérêt du hashCode est de comparer deux identifiants de manière plus rapide que l'appel de equals. En fait user*item comme je l'ai fait tout à l'heure c'est trop compliqué pour être vraiment intéressant. il vaudrait mieux faire un hashCode qui retourne juste user (ou item) comme ça si les deux users sont identiques on appelle equals pour comparer user ET item (donc on aura fait 3 comparaisons), mais en général on les deux users sont différents avec le hashCode on n'aura comparé que l'user (et donc fait 1 seule comparaison). En moyenne on fait donc moins de 2 comparaisons c'est plus rapide. Après à toi de voir s'il est plus intéressant de mettre user ou item pour qu'on appelle le moins souvent equals. Mais tout ceci ce n'est que de l'optimisation, ça ne change rien au fait que de toute façon le hashCode est complété par equals.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Remarque : en y repensant il serait peut-être mieux d'utiliser une map de type ConcurrentHashMap<Integer,ConcurrentHashMap<Integer,Stone>>
Concurrent, c'est parce que tu vas être sur ton serveur et que plusieurs personnes pourraient y accéder en même temps. Et l'imbrication des deux c'est pour t'éviter ton type couple, et la manipulation du hashCode, parce qu'en fait si il y a beaucoup de hashCode identiques tu risque de faire beaucoup de tests equals et perdre en efficacité.
Du coup on considère que chaque utilisateur a sa propre HashMap où l'on récupère les item.
Concurrent, c'est parce que tu vas être sur ton serveur et que plusieurs personnes pourraient y accéder en même temps. Et l'imbrication des deux c'est pour t'éviter ton type couple, et la manipulation du hashCode, parce qu'en fait si il y a beaucoup de hashCode identiques tu risque de faire beaucoup de tests equals et perdre en efficacité.
Du coup on considère que chaque utilisateur a sa propre HashMap où l'on récupère les item.
Stone put(Integer userID,Integer itemID,Stone s) { if (!map.contains(userID)) map.put(userID,new ConcurrentHashMap<Integer,Stone>()); return map.get(userID).put(itemID,s); } Stone get(Integer userID,Integer itemID) { if (!map.contains(userID)) return null; else return map.get(userID).get(itemID,s); }