hashCode, qui s'en sert ? - Java - Programmation
Marsh Posté le 23-07-2002 à 16:02:51
bin si tu veux générer un hash de l'id de ton objet pour obetenir facilement un identifiant de ce dernier
Marsh Posté le 23-07-2002 à 16:05:34
DarkLord a écrit a écrit : bin si tu veux générer un hash de l'id de ton objet pour obetenir facilement un identifiant de ce dernier |
C'est fiable ? Tu t'en sers toi ?
Marsh Posté le 23-07-2002 à 16:09:12
Cherrytree a écrit a écrit : C'est fiable ? Tu t'en sers toi ? |
Non parce que j'en ai jamais eu besoin mais plein d'objet l'utiliseent de manière transparent (HashMap par exemple)
Sinon ca dépend sur quel objet tu utilises hashcode mais l'algo est fiable oui. C'est pas un truc Java de toutes manières.
Marsh Posté le 23-07-2002 à 16:14:01
DarkLord a écrit a écrit : Non parce que j'en ai jamais eu besoin mais plein d'objet l'utiliseent de manière transparent (HashMap par exemple) Sinon ca dépend sur quel objet tu utilises hashcode mais l'algo est fiable oui. C'est pas un truc Java de toutes manières. |
OK, ça me va alors.
Marsh Posté le 23-07-2002 à 16:15:02
DarkLord a écrit a écrit : Non parce que j'en ai jamais eu besoin mais plein d'objet l'utiliseent de manière transparent (HashMap par exemple) Sinon ca dépend sur quel objet tu utilises hashcode mais l'algo est fiable oui. C'est pas un truc Java de toutes manières. |
l'algo pour les objets non-string est simple : c'est l'adresse memoire donc c'est unique
pour les Strings c'est vraiment un algo
Renaud
Marsh Posté le 23-07-2002 à 16:15:39
- Renaud - a écrit a écrit : l'algo pour les objets non-string est simple : c'est l'adresse memoire donc c'est unique pour les Strings c'est vraiment un algo Renaud |
voilà c'est la précision que j'attendais. Merci Renaud
Marsh Posté le 23-07-2002 à 16:21:19
- Renaud - a écrit a écrit : l'algo pour les objets non-string est simple : c'est l'adresse memoire donc c'est unique pour les Strings c'est vraiment un algo Renaud |
Merci !
Marsh Posté le 23-07-2002 à 16:49:32
Le hashcode c'est important de savoir à quoi il sert !
sinon, tôt ou tard tu vas te poser de droles de question et passer des journées entères à débugguer !
le hashcode est utilisé pour créér un entier à partir d'un objet.
Le principe de base c'est : si 2 objets sont égaux, ils doivent avior le même hascode.
C'est la règle à respecter quand tu redéfinies a méthode hascode.
Maintenant la question qui tue : "mais à quoi ca sert la méthode hashcode ??"
et la réponse qui tue : c'est utilisé dans les algo de hashage.
par exemple : les HashMap (ou HashTable).
Le principe : associé à des objets Clef des objet Value. Le but étend que la recherche de la valeur à partir de la clef soit rapide.
en interne ca fonctionne à peu près comem ca :
on créé un tableau de Vecteur en mémoire d'une taille T.
quand on souhaite ajouter un couple (clef, valeur), on hash la clef, ce qui nous donne un identifiant. On calcul l'identifiant modulo T, ce qui nous donne un index I dans le tableau, et on ajoute le couple clef-valeur dans le vecteur situé à l'index I du tableau.
Ensuite, quand on recherchera une valeur dans le tableau, à la place de parcourir tout le tableau à la recherche de la clef, on fait la même opération pour trouver l'index, et on cherche la clef dans le vecteur se trouvant à cet index dans le tableau (en utilisant la méthode equals).
(J'espère que j'ai été à peu près clair)
si vous avez bien compris le principe de l'algo des hasmap, vous voyez que c'est important de ne pas faire n'importe quoi avec le hascode : par exemple, si pour un objet qui n'a pas changé d'état, 2 appels à la méthode hashcode ne donne pas le même résultat, on ne le retrouveras jamais dans le HashMap (puisqu'on ne regardera pas au bon index). En plus, si on redéfinit le haschode, il faut quasiment obligatoirement redéfinir le equals ! sinon, on tombera au bon index, mais on ne retrouveras pas l'objets dans le vecteur ...
Un truc qui marche quasi-toujours pour redéfinir le hascode, c'est d'aditionner les hascode de ses attributs. C'est une bonne méthode pour avoir un algo de hashage correct. ex :
Code :
|
le problème, c'est que à chaque appel au hascode, on va déclenché l'appel à 2 hashcode de String (qui sont assez lourd).
Pour les petites applis ca passe, mais dans le cas d'EJB par exemple, utiliser masivement cette technique (pour les PrimaryKey) risque d'entrainer un écroulement du serveur !
la plupart du temps, retourner le hashage d'un seul des attributs est suffisant. Bien sur, il faut choisir l'attribut qui aura le plus de chance de renvoyer un hascode différents dans le cas d'objets différents. (si un hascode retourne toujours la même valeur, la recherche dans une Map devient aussi lente (voir plus) qu'une recherche itérative dans un tableau).
Dans le cas idéal, l'objet possède un identifiant unique (ex : id dans la base de donnée) et il suffira de retourner cet entier.
j'espère que j'ai pas été trop incompréhensible, et merci de voter attention.
Marsh Posté le 23-07-2002 à 16:50:24
benou >>> (I'm impressed)
Marsh Posté le 23-07-2002 à 16:52:03
dans le cas des String, le hascode est généré à partir de la suite de char => pour chaque appel au hascode on parcours (du moins en partie) le tableau de caractèr qui la compose.
C'est efficace comme algo, mais c'est loin d'être performant ...
dans le cas des objets ne redéfinissant pas le hascode, c'est la méthode de Object qui est utilisé (bien sur). Elle retourne l'emplacement mémoire de l'objet. C'est performant, mais loin d'être efficace.
Marsh Posté le 23-07-2002 à 16:52:33
DarkLord a écrit a écrit : benou >>> (I'm impressed) |
j'aurais pu encore en parler un moment mais j'avais peur de devenir chiant ...
Marsh Posté le 23-07-2002 à 17:00:48
je me souviens de quelqu'un qui cherchait un bug dans une appli EJB : ca fesait un bug complétement aléatoire.
Ca venait du fait qu'il utilisait un String buffer comme attribut pour stocker des chaines de caractères. Et il utilisait évidement le hascode du StringBuffer pour générer le hascode de l'objet ...
mauvaise idée : le hascode d'un StringBuffer varie si la capacité change (même si le texte qu'il contient est le même).
Je crois qu'il serait encore en train de débuguer si je ne lui avais pas expliqué comment ca marchait le hascode ...
En fait, le hascode était utilisé car le conteneur EJB fesait de l'optimisation en fesant du cache sur certains objets. Mais ca on l'a découvert qu'après : c'était complétement invisible au niveau de son code : c'était le conteneur qui fesait ca un coup de temps en temps.
Depuis ce temps là, je fais bien gaffe quand j'écris cette méthode !
Marsh Posté le 23-07-2002 à 17:03:57
benou a écrit a écrit : dans le cas des String, le hascode est généré à partir de la suite de char => pour chaque appel au hascode on parcours (du moins en partie) le tableau de caractèr qui la compose. C'est efficace comme algo, mais c'est loin d'être performant ... dans le cas des objets ne redéfinissant pas le hascode, c'est la méthode de Object qui est utilisé (bien sur). Elle retourne l'emplacement mémoire de l'objet. C'est performant, mais loin d'être efficace. |
Pourquoi c loin d'êter efficace ?
on récupère bien un identifiant unique... pourquoi s'emmerder avec d'autres trucs !?
Marsh Posté le 23-07-2002 à 17:04:32
heu, cherry, c'est toi qui posait la question ... t'as compris le principe ?
Marsh Posté le 23-07-2002 à 17:05:27
benou a écrit a écrit : j'aurais pu encore en parler un moment mais j'avais peur de devenir chiant ... |
Vas-y, défoule toi, ça m'intéresse.
Marsh Posté le 23-07-2002 à 17:06:46
benou a écrit a écrit : heu, cherry, c'est toi qui posait la question ... t'as compris le principe ? |
Ouep, j'ai compris. Je me demande si l'algo que j'ai en face de moi ne peut pas être mieux pensé.
Marsh Posté le 23-07-2002 à 17:11:07
el_gringo a écrit a écrit : Pourquoi c loin d'êter efficace ? on récupère bien un identifiant unique... pourquoi s'emmerder avec d'autres trucs !? |
houlala, tu vas m'entrainer dans un post de fou encore une fois ...
Je vais simplifier pour être court
bon, le but d'un algo de hashage c'est de trouver une valeur dans un tableau rapidement : en "déterminant" l'index auxquel devrait se trouver l'objet plutot que de parcourir tout le tableau.
Si la Map contient 3 éléments, le parcours sera super rapide : disons 10 mSec.
si tu mets 20 mSec à calculer le hascode d'une string, ok, tu vas tout de suite trouver l'index de ton élément, mais tu vas mettre plus de temps que si tu avais fait un bête parcours
Marsh Posté le 23-07-2002 à 17:20:52
benou a écrit a écrit : houlala, tu vas m'entrainer dans un post de fou encore une fois ... Je vais simplifier pour être court bon, le but d'un algo de hashage c'est de trouver une valeur dans un tableau rapidement : en "déterminant" l'index auxquel devrait se trouver l'objet plutot que de parcourir tout le tableau. Si la Map contient 3 éléments, le parcours sera super rapide : disons 10 mSec. si tu mets 20 mSec à calculer le hascode d'une string, ok, tu vas tout de suite trouver l'index de ton élément, mais tu vas mettre plus de temps que si tu avais fait un bête parcours |
Ouais, ms g l'impression que t'as pas compris ma question :
Pourquoi est ce qu'on utiliserai pas toujours la méthode hashcode héritée de Object.
ça calcul un hashcode unique et rapidement.
Quel est l'inconvénient ds la cas de ta classe Client par exemple. Je vois pas l'intérêt que tu as de surcharger "hashcode ()", pour la remplacer par une méthode hashcode plus lente (vu qu'elle calcule 2 hashcode de String)...
Marsh Posté le 23-07-2002 à 17:22:15
gringo >>> Et si tu as deux instances de Client avec le meme nom et le meme prénom tu y as pensé ?
Marsh Posté le 23-07-2002 à 17:32:40
DarkLord a écrit a écrit : gringo >>> Et si tu as deux instances de Client avec le meme nom et le meme prénom tu y as pensé ? |
Haaaaaaa... c pas bête ça, tient !
Marsh Posté le 23-07-2002 à 17:58:33
Cherrytree a écrit a écrit : Vas-y, défoule toi, ça m'intéresse. |
cool !
bon, ben je peux aussi parler de l'efficacité du hascode.
Qu'est qui fait qu'un algo de hashage sera efficace ou nom ?
la réponse : il faut optimizer le fait que pour 2 objets différents, les hascode soient différents.
on va prendre le cas de la classe Bille.
On veut pouvoir retrouver facilement une bille dans un sac de bille.
Notre sac de bille va être un tableau de vecteur. Le but c'est que les billes soient uniformément répartir dans le tableau, et pour le cas où deux billes doivent se trouver au même emplacement dans le tableau, on utilise le vecteur pour les stocker tous les deux à cet emplacement.
Le fait d'utiliser un taleau de vecteur nous permet de stocker un nombre de bille infinit (les vecteurs s'allongent).
le principe d'une recherche d'une bille dans le sac :
1 - on calcul le hascode de la bille
2 - on calcul lui applique un modulo taille du tableau
3 - on sélectionne le vecteur situé à cet index
4 - on parcourt le vecteur à la recherche de la bille
Donc, si on a un tableau de taille 100 avec des vecteurs de taille moyenne de 5 (contenance du sac : 500), la recherche de la bille prendra : le temps du calcul du hascode + le temps du parcours du vecteur de taille 5 (2,5 tests en moyenne).
Par une méthode itérative sur un tableau de base, il faudrait parcourir le tableur en entier (250 tests en moyenne). On voit bien la gain de l'algo de hashage.
Ce qu'il faut maintenant, c'est que nos billes soient bien réparties dans le tableau : si il n'y a que quelques cases du tableau qui sont pleines, les vecteurs vont grandir et donc le temps de parcours du vecteur va s'allonger => on perd en efficacité.
Conclusion : pour avoir un algo de hashage efficace, il faut qu'il retourne des entiers les plus différents dans la plus grande plage possible
On va prendre un exemple avec notre classe Bille : voici ses attributs :
Code :
|
le truc de base c'est de faire ces méthodes là :
Code :
|
Ca ce sera toujours la même.
Maintenant essayant cette méthode de hashage là :
Code :
|
Cette méthode hashcode est correct. Elle est performante, elle respecte le principe du hascode identique si objet identique.
Mais il ne sera pas du tout efficace :
Toutes les billes vont être stockées dans la case 1 du tableau dans un vecteurs énorme => une recherche reviendra à faire une recherche itérative dans un vecteur.
bref, c'est nul.
On pourrait se dire que pour avoir des valeurs bien distincts les une des autres, on pourrait faire ca :
Code :
|
Là c'est pas nul, c'est catastrophique : ca va plus marcher. On va mettre une bille dans une case aléatoir du tableau et quand on va aller la rechercher, on va regarder dans une case aléatoire. Bref ca peut marcher mais y a pas beaucoup de chance. (remarque plus le tableau sera petit, plus ca marchera souvent)
donc il faut que le hashcode se base sur son état : qu'il retourne un code qui le différencie bien des autres si il est lui même bien différents des autres.
Par exemple, on pourrait utiliser le poid :
Code :
|
La ca va marcher pas mal : les billes ont rarement le même poid => les hascode seront bien différents. Et dans le cas où les billes sont égales (identiques) elles ont le même poid.
Bref, cette méthode est pas mal : on va répartir les billes dans le tableau en fonction de leur poid.
Vu que ca marche bien avec un attribut (le poid), on pourrait très bien essayer d'améliorer les choses en se servant d'un 2e attribut : exemple la marque. Pour ca, on peut utiliser le hascode de la marque (qui est de type String). On l'ajoute au poid et hop, on obtient un hashcode plus efficace : 2 billes de même poid seront rangées dans des case différentes même si elles ont le même poid.
Code :
|
bon, si c'est mieux avec 2 attributs, ca doit être mieux avec 4 !
Code :
|
bon, c'est vrai, c'est encore mieux : on étale la plage de valeur possible et les hascode seront de plus en plus différents : la moindre différence entre 2 billes entrainera un hashcode différents.
Maintenant il y a un autre problème : il ne faudrait pas non plus que la méthode hascode soit trop longue : si on a très peu de bille dans le sac, on va passer tout notre temps à calculer le hascode alors qu'il serait plus rapide de regarder dans toutes les cases ...
Bref, il n'est pas facile de déterminer quel est l'algo de hashage le plus efficace.
Moi, pour notre exemple, j'aurais fait un truc dans le genre :
Code :
|
comme ca, si le poid est précis et la couleur aussi, le hascode différencera bien les billes.
Bon, après si on veux compliquer les choses, il faut aussi faire attention à l'ordre des tests qui sont fait dans le equals : il faut mettre les tests qui ont le plus de chance d'être faux en premier ...
Marsh Posté le 23-07-2002 à 18:02:22
DarkLord a écrit a écrit : gringo >>> Et si tu as deux instances de Client avec le meme nom et le meme prénom tu y as pensé ? |
bha oui. Le problème c'est pas hashcode c'est equals !
il va forcément falloir que tu redéfinnisse equals. Sinon ton objet sera "faux" et tu auras des problèmes quand tu voudra rendre tes objets perssistants (sérialisation, bdd) ou distribués. C'est à dire quand tu pourras avoir un objet identique (égaux) avec 2 adresses mémoires différentes.
Et une fois que le equals est redéfini, tu es obligé de redéfinir le hashcode si tu veux t'en servir dans une Map (ou tout autre objet qui utilise la méthode hashcode) sinon le principe du "2 objets égaux ont le même hascode" devient faux. Et là ca va te faire des bugs durs à trouver !
Marsh Posté le 23-07-2002 à 18:05:54
benou > bravo, c'est hyper classe comme explication. Et j'ai presque tout compris. Maintenant, la question qui me vient à l'esprit, c'est quand est-ce que je redéfinis un hashcode, et quand est-ce que j'utilise la méthode héritée de Object ?
Marsh Posté le 23-07-2002 à 18:06:47
benou a écrit a écrit : bha oui. Le problème c'est pas hashcode c'est equals ! il va forcément falloir que tu redéfinnisse equals. Sinon ton objet sera "faux" et tu auras des problèmes quand tu voudra rendre tes objets perssistants (sérialisation, bdd) ou distribués. C'est à dire quand tu pourras avoir un objet identique (égaux) avec 2 adresses mémoires différentes. Et une fois que le equals est redéfini, tu es obligé de redéfinir le hashcode si tu veux t'en servir dans une Map (ou tout autre objet qui utilise la méthode hashcode) sinon le principe du "2 objets égaux ont le même hascode" devient faux. Et là ca va te faire des bugs durs à trouver ! |
C'est vraiment un Thread très intéressant, j'aurai jamais pensé en posant ma question !
Marsh Posté le 23-07-2002 à 18:09:29
Cherrytree a écrit a écrit : benou > bravo, c'est hyper classe comme explication. Et j'ai presque tout compris. Maintenant, la question qui me vient à l'esprit, c'est quand est-ce que je redéfinis un hashcode, et quand est-ce que j'utilise la méthode héritée de Object ? |
Tant que tu ne te sers pas des Map, de systèmes de cache, d'entity bean (persistence) ou de trucs dans le gener, tu n'en as pas besoin.
mais dès que tu veux mettre un object dans un Vecteur, tu dois déjà gérer une méthode equals. Dans ce cas là, ajoute la méthode hascode (même si elle est pas efficace ou performante). C'est une mesure de précaution pour l'avenir ...
Marsh Posté le 23-07-2002 à 18:11:24
Cherrytree a écrit a écrit : C'est vraiment un Thread très intéressant, j'aurai jamais pensé en posant ma question ! |
Je trouve que c'est un truc dont on parle pas assez quand on apprend le Java. Du coup y a vraiment peu de gens qui connaissent ... alors qu'on s'en sers souvent (sans le savoir)
Marsh Posté le 23-07-2002 à 18:11:53
benou a écrit a écrit : Tant que tu ne te sers pas des Map, de systèmes de cache, d'entity bean (persistence) ou de trucs dans le gener, tu n'en as pas besoin. mais dès que tu veux mettre un object dans un Vecteur, tu dois déjà gérer une méthode equals. Dans ce cas là, ajoute la méthode hascode (même si elle est pas efficace ou performante). C'est une mesure de précaution pour l'avenir ... |
Je découvre un nouvel univers on dirait. Euh, tu as appris ça où ? Dans le livre de Eckel ?
Marsh Posté le 23-07-2002 à 18:13:53
Cherrytree a écrit a écrit : Je découvre un nouvel univers on dirait. Euh, tu as appris ça où ? Dans le livre de Eckel ? |
des souvenirs d'un cours de progs en 1ere année d'info où un prof avait parlé des algos de hashage... et puis avec un peu d'expérimentation ...et aussi beaucoup de lecture et relecture de la javadoc des méthodes hashcode et equals de Object !
j'ai jamais eu un seul cours d'algorythmique !
Marsh Posté le 23-07-2002 à 18:18:13
benou a écrit a écrit : des souvenirs d'un cours de progs en 1ere année d'info où un prof avait parlé des algos de hashage... et puis avec un peu d'expérimentation ...et aussi beaucoup de lecture et relecture de la javadoc des méthodes hashcode et equals de Object ! j'ai jamais eu un seul cours d'algorythmique ! |
Chapô, tu es un vrai, toi.
Marsh Posté le 23-07-2002 à 18:36:07
benou a écrit a écrit : j'aurais pu encore en parler un moment mais j'avais peur de devenir chiant ... |
(:D)
Marsh Posté le 23-07-2002 à 18:42:57
bon
je fous ce topic dans mes favoris
c la 1e fois que je fais ça --> benou:
il faudrait pê mettre ce topic dans la liste des "autres topics a lire", dans le topic JAVA FAQ.
sinon je vais ajouter mon petit grain de sel:
en regardant les sources du jdk (c'est tres instructif, et drôle parfois), j'ai vu qu'une classe (et surement d'autres), dont j'ai aussi oublié le nom, cachait la valeur de son hashcode, pour ne pas devoir le recalculer à chaque fois. pas con...
Marsh Posté le 23-07-2002 à 22:27:55
DarkLord a écrit :
Citation : benou >>> (I'm impressed) |
cherrytree a écrit :
Citation : benou > bravo, c'est hyper classe comme explication. |
--greg-- a écrit :
Citation : |
ca fait plaisir
Marsh Posté le 23-07-2002 à 22:55:35
benou a écrit a écrit : ca fait plaisir |
Ben, faut dire aussi que tu t'es salement cassé le cul pour la communauté. C'est normal qu'elle te remercie. Tu sais si ça te plait d'expliquer des trucs comme celui-là, tu peux toujours ouvrir un topic => les astuces de tonton benou. Je serais un fan assidu, crois-moi.
Marsh Posté le 23-07-2002 à 23:06:12
Cherrytree a écrit a écrit : Ben, faut dire aussi que tu t'es salement cassé le cul pour la communauté. C'est normal qu'elle te remercie. Tu sais si ça te plait d'expliquer des trucs comme celui-là, tu peux toujours ouvrir un topic => les astuces de tonton benou. Je serais un fan assidu, crois-moi. |
Marsh Posté le 23-07-2002 à 23:43:25
c'est vrai que j'aime bien expliquer ... j'ai peut-être loupé ma vocation : j'aurais du être prof.
mais bon, je pense pas être assez balèze pour ce genre de "newsletter".
bon il est tard ... tonton benou va aller se coucher maintenant
Marsh Posté le 24-07-2002 à 00:02:17
benou a écrit a écrit : c'est vrai que j'aime bien expliquer ... j'ai peut-être loupé ma vocation : j'aurais du être prof. mais bon, je pense pas être assez balèze pour ce genre de "newsletter". bon il est tard ... tonton benou va aller se coucher maintenant |
en fait on devrait tenir à jour un site séparé avec la faq et ce genre de topic, revu & corrigé (c-a-d nettoyé quoi), ça serait plus pratique.
je suis partant pour m'en occuper à temps partiel, mais bon, j'entend déjà d'ici les railleries (justifiées) concernant le trombi
Marsh Posté le 24-07-2002 à 00:05:07
--greg-- a écrit a écrit : en fait on devrait tenir à jour un site séparé avec la faq et ce genre de topic, revu & corrigé (c-a-d nettoyé quoi), ça serait plus pratique. je suis partant pour m'en occuper à temps partiel, mais bon, j'entend déjà d'ici les railleries (justifiées) concernant le trombi |
c'est un truc auxquel je pensais depuis un moment ...
que pensais vous d'un site HTML tout bête dans lequel on listerai les meilleurs "trucs" pour le JAva qui ont été écrit sur ce forum ?
faudrait mettre ca sur un hebergeur gratuit pour que ce soit disponible tout le temps (ce serait plus pratique que sur la machine à quelqu'un ...
Marsh Posté le 24-07-2002 à 00:13:09
--greg-- a écrit a écrit : en fait on devrait tenir à jour un site séparé avec la faq et ce genre de topic, revu & corrigé (c-a-d nettoyé quoi), ça serait plus pratique. je suis partant pour m'en occuper à temps partiel, mais bon, j'entend déjà d'ici les railleries (justifiées) concernant le trombi |
Quant à moi j'entends encore l'elastique de mon slip claquer sur mon ventre.
naturellement !
Marsh Posté le 24-07-2002 à 00:14:09
benou a écrit a écrit : c'est un truc auxquel je pensais depuis un moment ... que pensais vous d'un site HTML tout bête dans lequel on listerai les meilleurs "trucs" pour le JAva qui ont été écrit sur ce forum ? faudrait mettre ca sur un hebergeur gratuit pour que ce soit disponible tout le temps (ce serait plus pratique que sur la machine à quelqu'un ... |
D'accord. Si je peux contribuer pour quoi que ce soit, j'en suis.
Marsh Posté le 23-07-2002 à 15:59:19
Heu, je suis confronté à ce chose étrange dans un source. J'ai lu la doc' là-dessus, mais ça m'a l'air un peu space comme engin. Y en a qui se servent de ça ? Dans quels cas ça se justifie-t-il ?
---------------
Le site de ma maman