Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1711 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  HashMap.hash() ils ont pété un plomb ou quoi?

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

HashMap.hash() ils ont pété un plomb ou quoi?

n°315061
Taz
bisounours-codeur
Posté le 21-02-2003 à 16:13:30  profilanswer
 

alors je me casse le cul à faire une bonne fonction de hashage, j'en trouve une optimale pour mes données (c'est à dire dans le cas de mon traitement, j'ai des clefs uniques et d'autres données faciles, donc j'ai presque quelque chose de parfait). je commence mes tests et vlan, y a 30% de collisions alors que j'avais prévu qu'il n'y en aurait presque pas (de l'ordre de 1 pour 1000).  
 
et puis je tombe la dessus
 

Code :
  1. /**
  2.      * Returns a hash value for the specified object.  In addition to  
  3.      * the object's own hashCode, this method applies a "supplemental
  4.      * hash function," which defends against poor quality hash functions.
  5.      * This is critical because HashMap uses power-of two length  
  6.      * hash tables.<p>
  7.      *
  8.      * The shift distances in this function were chosen as the result
  9.      * of an automated search over the entire four-dimensional search space.
  10.      */
  11.     static int hash(Object x) {
  12.         int h = x.hashCode();
  13.         h += ~(h << 9);
  14.         h ^=  (h >>> 14);
  15.         h +=  (h << 4);
  16.         h ^=  (h >>> 10);
  17.         return h;
  18.     }


 
ils sont pas bien ou quoi? ça me fout tout en l'air!

mood
Publicité
Posté le 21-02-2003 à 16:13:30  profilanswer
 

n°315073
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 16:31:33  profilanswer
 

Normalement, si tu écris bien ton code, tu devrais pouvoir faire en sorte que la fonction standard de hachage ne soit pas appelée. Tu redéfinis le hachage comment ?

n°315083
Taz
bisounours-codeur
Posté le 21-02-2003 à 16:45:09  profilanswer
 

ben je fais le truc comme il faut en redéfinissant hashCode pour ma class de donénes, mais bon, je vois pas comment passer outre ça
 

Code :
  1. public Object get(Object key) {
  2.         Object k = maskNull(key);
  3.         // la spa mon hash qui est utilisé  
  4.         int hash = hash(k);
  5.         // Grrrrrrrrr
  6.         int i = indexFor(hash, table.length);
  7.         Entry e = table[i];
  8.         while (true) {
  9.             if (e == null)
  10.                 return e;
  11.             if (e.hash == hash && eq(k, e.key))
  12.                 return e.value;
  13.             e = e.next;
  14.         }
  15.     }


n°315090
benou
Posté le 21-02-2003 à 16:53:39  profilanswer
 

facile de t'en sortir :
 
Tu étends HashMap et tu surcharges la méthode static hash( je crois qu'on peut) en ca :  
 

Code :
  1. static int hash(Object x) {
  2.        return x.hashCode();
  3. }


 
et voilou !

n°315093
Taz
bisounours-codeur
Posté le 21-02-2003 à 16:56:08  profilanswer
 

d'ailleurs a y regarder de plus pres, l'implémentation est désastreuse (pas sur le fond sur la forme). les mecs qui ont fait ça devaient pas etre tres sensibles à la réutilisabilité ou payer à la ligne, par ce que plus je lis les sources de l'API, plus je flippe: c'est pas rare de trouver dans un module 4/5 fonctions de 15 lignes ou plus qui dont le code est exactement le meme sauf le return final qui differe. n'importe quoi!

n°315097
Taz
bisounours-codeur
Posté le 21-02-2003 à 16:59:44  profilanswer
 

exemple en image
 

Code :
  1. Entry getEntry(Object key) {
  2.     Object k = maskNull(key);
  3.     int hash = hash(k);
  4.     int i = indexFor(hash, table.length);
  5.     Entry e = table[i];
  6.     while (e != null && !(e.hash == hash && eq(k, e.key)))
  7.         e = e.next;
  8.     return e;
  9. }
  10. public Object get(Object key) {
  11.     Object k = maskNull(key);
  12.     int hash = hash(k);
  13.     int i = indexFor(hash, table.length);
  14.     Entry e = table[i];
  15.     while (true) {
  16.         if (e == null)
  17.             return e;
  18.         if (e.hash == hash && eq(k, e.key))
  19.             return e.value;
  20.         e = e.next;
  21.     }
  22. }

 
 
les mecs ont meme pas été foutu d'écrire la meme boucle, ils ont voulu se démarquer faut croire. bref l'une fait return e et l'autre return e.value
minable
 
 
ben je vais surcharger, mais je trouve que ça craint

n°315099
benou
Posté le 21-02-2003 à 16:59:55  profilanswer
 

là je demande à voir : l'implémentation de ces classes là a du être tunnée à mort !!!

n°315100
Taz
bisounours-codeur
Posté le 21-02-2003 à 17:00:44  profilanswer
 

benou a écrit :

là je demande à voir : l'implémentation de ces classes là a du être tunnée à mort !!!

à ton aise. t'en veux d'autres?
 
edit: l'implémentation de Stack est très discutable. héritage, :non:, c'est clair que c'etait vraiment trop compliqué de faire un adaptateur. si les mecs avaient pas ecrit 2 fois la meme chose, ils auraient peut etre eu le temps de réfléchir un peu plus.
 
je decrouvre l'API, et beaucoup de choses que j'y vois sont loin de me ravir  :o


Message édité par Taz le 21-02-2003 à 17:13:35
n°315105
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 17:14:00  profilanswer
 

Je suis d'accord avec Taz. L'implémentation de plein de classes de base du JDK seraient clairement à revoir. Souvent, il y n'y aurait pas grand chose à changer, mais on y trouve régulièrement des petites horreurs sans aucune justification (du type efficacité). Simplement, personne ne s'en est plaint, alors personne chez Sun ne les a modifiées.

n°315134
R3g
fonctionnaire certifié ITIL
Posté le 21-02-2003 à 17:53:56  profilanswer
 

++Taz a écrit :

alors je me casse le cul à faire une bonne fonction de hashage, j'en trouve une optimale pour mes données (c'est à dire dans le cas de mon traitement, j'ai des clefs uniques et d'autres données faciles, donc j'ai presque quelque chose de parfait). je commence mes tests et vlan, y a 30% de collisions alors que j'avais prévu qu'il n'y en aurait presque pas (de l'ordre de 1 pour 1000).  
 
et puis je tombe la dessus
 

Code :
  1. /**
  2.      * Returns a hash value for the specified object.  In addition to  
  3.      * the object's own hashCode, this method applies a "supplemental
  4.      * hash function," which defends against poor quality hash functions.
  5.      * This is critical because HashMap uses power-of two length  
  6.      * hash tables.<p>
  7.      *
  8.      * The shift distances in this function were chosen as the result
  9.      * of an automated search over the entire four-dimensional search space.
  10.      */
  11.     static int hash(Object x) {
  12.         int h = x.hashCode();
  13.         h += ~(h << 9);
  14.         h ^=  (h >>> 14);
  15.         h +=  (h << 4);
  16.         h ^=  (h >>> 10);
  17.         return h;
  18.     }


 
ils sont pas bien ou quoi? ça me fout tout en l'air!


Bon alors là j dois avouer mon inculture, mais je comprends rien à cette fonction. En fait je ne suis pas très familire des opérateurs utilisés. Quelqu'un aurit-il la bonté de m'expliquer ce qui se passe ? (genre les opérateurs ~ et >>>, je connaissais pas).

mood
Publicité
Posté le 21-02-2003 à 17:53:56  profilanswer
 

n°315136
Taz
bisounours-codeur
Posté le 21-02-2003 à 17:58:13  profilanswer
 

ce sont des opérations bit à bit
~ complément
>>>, >> et << sont des décalages
& et binaire
| ou binaire
^ ou binaire exclusif
 
à toi de tester

n°315137
R3g
fonctionnaire certifié ITIL
Posté le 21-02-2003 à 18:00:00  profilanswer
 

A oui le complement, j'y pensais plus. Sinon pour les décalages de bit je connaissais, mais alors quelle est la différence entre >> et >>> ?

n°315141
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 18:05:47  profilanswer
 

Remise à zéro des bits qui apparaissent lors du décalage dans un cas, et décalage circulaire dans l'autre cas, si ma mémoire est bonne.

n°315143
R3g
fonctionnaire certifié ITIL
Posté le 21-02-2003 à 18:08:26  profilanswer
 

Ah ok d'accord. Merci beaucoup :jap:

n°315147
Taz
bisounours-codeur
Posté le 21-02-2003 à 18:14:26  profilanswer
 

presque
 
>> est un décalage à droite signé qui insère des 0 ou des 1 selon le signe (conservation)
>>> décalage à droite avec entrée de 0 à gauche
<< décalage à gauche avec injection de 0

n°315149
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 18:15:39  profilanswer
 

C'est effectivement plus logique que ce que j'ai dit.  :jap:

n°315150
benou
Posté le 21-02-2003 à 18:16:46  profilanswer
 

++Taz a écrit :

à ton aise. t'en veux d'autres?
 
edit: l'implémentation de Stack est très discutable. héritage, :non:, c'est clair que c'etait vraiment trop compliqué de faire un adaptateur. si les mecs avaient pas ecrit 2 fois la meme chose, ils auraient peut etre eu le temps de réfléchir un peu plus.


je suis d'accord avec toi. Mais je crois que concernant la stack, ils ont préferrer permettre au développeur d'accéder aux méthodes de Vector avec une stack pour une raison de praticité.
 
Mais je suis d'accord avec toi : ce n'est aps logique que Stack hérite de Vector !
 
 
sinon, concernant la HashMap, je crois pas qu'elle soit le résulta d'un stagiaire qui a écrit ca vite fait un vendredi soir ...
 
Ce genre de classe est utilisée partout => la performance de java est très dépendante de l'implémentation de ces classes.
 
D'ailleurs, les changements d'implémentation de la HashMap (et autre HashTable) ont été revu plusieurs fois au fur et à mesure des versions du JDK

n°315153
Taz
bisounours-codeur
Posté le 21-02-2003 à 18:19:05  profilanswer
 

ben pour la stack, l'encapsulation est pulvérisée :( . on dit que java est sure, quand je vois comment c'est facile de bousiller une pile  :sweat:

n°315156
benou
Posté le 21-02-2003 à 18:22:06  profilanswer
 

c'est un choix bordel ! t'as le droit de pas le partager (comme je le fais) mais juger la "sécurité" de java en fonction de ça c'est carément ridicule !  [:benou]


Message édité par benou le 21-02-2003 à 18:22:21
n°315157
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 18:22:25  profilanswer
 

Autre commentaire concernant Stack : elle est synchronisée (puisque Vector l'est), et son équivalent non synchronisé n'existe pas dans le JDK.
Or on a souvent besoin, quand on écrit ses propres classes, d'une pile qui ne soit pas synchronisée, et autant il est facile de rendre synchronisée une collection qui ne l'est pas (avec la méthode statique appropriée de la classe Collections) autant le contraire est, il me semble totalement impossible.
 
Pour HashMap, d'accord et pas d'accord benou. Certes cette classe-là a peut-être être revu par Sun, et, à leur décharge, la plupart des programmeurs ne savent pas écrire une fonction de hachage correcte. L'inconvénient, c'est que du coup, on se retrouve dans le cas de Taz quand on connaît bien ses données à hacher. Quitte à rajouter un tel code dans HashMap, il aurait été préférable de pouvoir le déconnecter simplement, même si par défaut, il est activé.


Message édité par BifaceMcLeOD le 21-02-2003 à 18:23:13
n°315158
benou
Posté le 21-02-2003 à 18:24:34  profilanswer
 

et ben j'ai donné la manip pour que ca fonctionne comme il veut !
 
ca prend 5 lignes à écrire à tout casser !!!! :o
 

n°315159
BifaceMcLe​OD
The HighGlandeur
Posté le 21-02-2003 à 18:25:34  profilanswer
 

++Taz a écrit :

ben pour la stack, l'encapsulation est pulvérisée :( . on dit que java est sure, quand je vois comment c'est facile de bousiller une pile  :sweat:  


Si tu veux une pile propre, tu te fais une interface nickel, et tu pourras en plus disposer plusieurs implémentations différentes (basée sur un ArrayList, un LinkedList, voire une implémentation plus délire).

n°315160
benou
Posté le 21-02-2003 à 18:27:59  profilanswer
 

si vous voulez des infos sur les méandre de l'implémentation et l'optimisation de cette classe, lisez ca : http://www.javaspecialists.co.za/archive/Issue054.html

n°315161
Taz
bisounours-codeur
Posté le 21-02-2003 à 18:28:06  profilanswer
 

le principale reproche, c'est que je n'ai vu le hashage supplémentaire mentionné nulle part dans la doc.

n°315163
benou
Posté le 21-02-2003 à 18:29:08  profilanswer
 

++Taz a écrit :

le principale reproche, c'est que je n'ai vu le hashage supplémentaire mentionné nulle part dans la doc.


ouep ! un point pour toi !

n°315168
Taz
bisounours-codeur
Posté le 21-02-2003 à 18:38:54  profilanswer
 

benou a écrit :

si vous voulez des infos sur les méandre de l'implémentation et l'optimisation de cette classe, lisez ca : http://www.javaspecialists.co.za/archive/Issue054.html

ça me fais froid dans le dos. justifier l'emploi de  de taille 2**n parce que c'est "plus rapide" de faire un mask qu'un modulo et ainsi introduire des problèmes de collisions et donc devoir rehasher pour pallier à cet effet secondaire, c'est de la science fiction  :heink:  
 
je comprends vraiment rien à la philosphie des programmeurs de l'API

n°315171
benou
Posté le 21-02-2003 à 18:42:53  profilanswer
 

je pense qu'ils ont du bencher cette classe et l'optimiser pour le meilleur résultat moyen, en se disant qu'en cas d'extrème importance des perfs, les développeurs ne serait pas à ca près de redévelopper l'algo de répartition.
 
ca se défend !

n°315179
dsls
Posté le 21-02-2003 à 18:52:00  profilanswer
 

benou a écrit :

facile de t'en sortir :
 
Tu étends HashMap et tu surcharges la méthode static hash( je crois qu'on peut) en ca :  
 

Code :
  1. static int hash(Object x) {
  2.        return x.hashCode();
  3. }


 
et voilou !


 
Je ne crois pas qu'on puisse surcharger une méthode statique ...
http://forum.java.sun.com/thread.j [...] ead=289648

n°315181
Taz
bisounours-codeur
Posté le 21-02-2003 à 18:52:52  profilanswer
 

le problème: l'utilisateur pas tres averti avec une fonction de hashage moyenne, de toutes façons, ne fera pas un usage tres aggresif, alors les perfs entre un % et un &, c'est surréaliste de considérer ça: certes çette optimsiation est effective, mais n'aura aucun impact sur son applciation. apres, y a le programmeur qui travaille sa fonction de hashage, veut une utilisation mémoire serrée et a besoin de performance: cette optimisation le dessert. apres si on part du principe qu'on est pété de RAM, qu'on aime bien offuscé son code avec des trucs binaires, qu'on a qu'une vague idée de ce qu'est une fonction de hash et qu'on veut un truc qui tourne à fond pour faire celui qui à la plus grosse.
sur ce, ben je vais faire ma hash_map perso

n°315192
benou
Posté le 21-02-2003 à 19:03:47  profilanswer
 

ouais, je crois que c'est ce qu'il te reste à faire...
 
si tu veux, prend le source de la HashMap de la jdk 1.3 ;) :D

n°315205
Taz
bisounours-codeur
Posté le 21-02-2003 à 19:12:32  profilanswer
 

je vais faire ma sauce maison mais je jetterai un oeil, merci  ;)

n°315388
nraynaud
lol
Posté le 22-02-2003 à 00:14:09  profilanswer
 

++Taz a écrit :

ben pour la stack, l'encapsulation est pulvérisée :( . on dit que java est sure, quand je vois comment c'est facile de bousiller une pile  :sweat:  


 
Je suis pas sûr que se soit réellement une connerie, j'ai pas encore tout capté, mais Meyer dans Eiffel fait aussi des (certaines) piles accessibles par index.
 
Mais j'ai pas compris en quoi ça ne serait pas crade.
 

n°315389
benou
Posté le 22-02-2003 à 00:21:01  profilanswer
 

c'est crade ! ca peut juste être pratique dans certains cas ...

n°315395
Taz
bisounours-codeur
Posté le 22-02-2003 à 00:59:32  profilanswer
 

nraynaud a écrit :


 
Je suis pas sûr que se soit réellement une connerie, j'ai pas encore tout capté, mais Meyer dans Eiffel fait aussi des (certaines) piles accessibles par index.
 
Mais j'ai pas compris en quoi ça ne serait pas crade.
 
 

ben ça n'a rien à voir avec une pile un vecteur. si on veut un vecteur, on utilise un vecteur et si on veut une pile, on utilise une pile. pourquoi permettre des opérations non-permises? c'est une régression. Utiliser l'héritage à la place de la compisition (ou d'un adaptateur dans le cas d'une pile),c 'est exposé inutilement des détails de l'implémentation. On peut alors corrompre les données de la pile puisque l'acces directe est permis. En plus l'héritage propage tous les problèmes de la super classe alors que la composition permet de les masquer.


Message édité par Taz le 22-02-2003 à 01:10:40
n°315398
Taz
bisounours-codeur
Posté le 22-02-2003 à 01:12:58  profilanswer
 

benou a écrit :

c'est crade ! ca peut juste être pratique dans certains cas ...

si tu veux utiliser un vecteur comme une pile, tu economiseras ton clacier puisque push est plus long a taper que add. Apres si vous etes pas d'accord sur ce qu'est une pile et que l'encapsulation vous semble etre une barriere injustifiée... j'y peux rien :sweat:  :whistle:

n°315404
verdoux
And I'm still waiting
Posté le 22-02-2003 à 02:01:07  profilanswer
 

C'est expliqué ici:
http://www.javaspecialists.co.za/archive/Issue054.html
 
Apparemment y a eu une grosse baisse de perfs sur la division euclidienne ce qui les a obligé à adopter des puissances de 2 pour le hachage.  
Mais cette puissance de 2 peut s'avérer catastrophique si la fonction de hachage utilisateur est pas mal foutue. Ils utilisent donc une petite bidouille, avec des décalages de bits pour, rédistribuer un peu les valeurs.


Message édité par verdoux le 22-02-2003 à 02:02:26
n°315660
darklord
You're welcome
Posté le 22-02-2003 à 21:31:58  profilanswer
 


 
benou a déjà donné ce lien :o


---------------
Just because you feel good does not make you right
n°315666
verdoux
And I'm still waiting
Posté le 22-02-2003 à 21:44:17  profilanswer
 

DarkLord a écrit :


 
benou a déjà donné ce lien :o


J'avais pas vu  :whistle:

n°315671
darklord
You're welcome
Posté le 22-02-2003 à 22:08:12  profilanswer
 

verdoux a écrit :


J'avais pas vu  :whistle:  


 
;)


---------------
Just because you feel good does not make you right
n°315673
nraynaud
lol
Posté le 22-02-2003 à 22:14:51  profilanswer
 

++Taz a écrit :

ben ça n'a rien à voir avec une pile un vecteur. si on veut un vecteur, on utilise un vecteur et si on veut une pile, on utilise une pile. pourquoi permettre des opérations non-permises? c'est une régression. Utiliser l'héritage à la place de la compisition (ou d'un adaptateur dans le cas d'une pile),c 'est exposé inutilement des détails de l'implémentation. On peut alors corrompre les données de la pile puisque l'acces directe est permis. En plus l'héritage propage tous les problèmes de la super classe alors que la composition permet de les masquer.


 
Merci, j'étais au courrant. Je crois que tu as répondu à côté.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  HashMap.hash() ils ont pété un plomb ou quoi?

 

Sujets relatifs
[crypto] En quoi ça consiste exactement la technique du hash ?Passer des HASH TABLE de scripts CGI en scripts CGI
[Perl] itérer sur les valeurs d'un tableau de hash de hash...[C] pété de rire et vieux gcc
ahhh, je pete un plomb !!!!! :-(Applet et HashMap : pb
je pète un plombs avec l'installation de postgreSQL sous winxpComboBoxModel + HashMap
[java] design... hashmap à 2 clés !? 
Plus de sujets relatifs à : HashMap.hash() ils ont pété un plomb ou quoi?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR