Les Set se basent sur quoi pour comparer ? [java] - Java - Programmation
Marsh Posté le 10-06-2004 à 18:04:47
les Sets ne sont pas pluggable, donc tu es dans la merde, soit tu fais un Set pluggable, soit tu wrappes chaque objet du Set dans un petit Proxy qui a le equals() comme tu veux.
Marsh Posté le 10-06-2004 à 18:12:30
petit exemple :
Code :
|
Marsh Posté le 11-06-2004 à 09:36:21
tu veux dire quoi par pluggable ?
--> sinon si je pige le truc, je fais une moulinette qui pour chaque objet de la liste instancie un wrapper, et appelle le equals sur ce wrapper pour tt les autres objets de la liste ?
Marsh Posté le 11-06-2004 à 10:25:41
nraynaud a écrit : petit exemple :
|
euh t'es gentil mais il suffit de redefinir la methode equals de MaClasse pour faire ça hein
Marsh Posté le 11-06-2004 à 10:32:11
bha dites donc ...
Rappel : Set est une interface => il faut savoir quel Objet cnocret tu utilises.
Dans l'API java, il y en a 2 : HashSet et TreeSet.
Si tu prends HashSet, il faudra forcément que tu passes par un wrapper comme l'a indiqué nraynaud. Ce wrapper sera juste une coquille qui contiendra l'objet que tu veux mettre dans le set, mais qui redéfinira à ta convenance la méthode equals de façon à ce que ca reflete la façon dont tu veux que le set soit géré.
Mais y a plus simple : si tu utilises TreeSet, tu peux le construire en lui passant un Comparator. Ce comparator sera utilisé pour "trier" l'arbre => 2 objet de ce set ne seront égaux que si la méthode compare du comparator retourne 0 => si tu veux 3 listes avec des notion dégalité séparé tu construit 3 TreeSet avec des Comparator différents.
Marsh Posté le 11-06-2004 à 10:38:04
euh le coup du wrapper c'etait pour pouvoir avoir un equals different de celui de l'objet en fait? bon d'accord
Marsh Posté le 11-06-2004 à 10:50:15
the real moins moins a écrit : euh le coup du wrapper c'etait pour pouvoir avoir un equals different de celui de l'objet en fait? bon d'accord |
En utilisant un HashSet t'as pas le choix ...
Marsh Posté le 11-06-2004 à 10:57:48
oui oui mais j'avais pas saisi qu'il voulait un equals different en fait. ben c naze comme idée, surtout si t'as pas les generics, c'est un coup à te manger des classcast
Marsh Posté le 11-06-2004 à 11:10:20
the real moins moins a écrit : oui oui mais j'avais pas saisi qu'il voulait un equals different en fait. ben c naze comme idée, surtout si t'as pas les generics, c'est un coup à te manger des classcast |
n'importe quoi
Marsh Posté le 11-06-2004 à 11:23:49
j'ai redéfini equals et hashcode pour que ca porte que sur les champs que je veux...
ca donne
Code :
|
en fait g pas besoin du wrapper si je redéfinis mon equals ?
Sinon pour le hash g une question : g lu dans la doc de Object qu'en fait le hash c l'adresse mémoire...donc si je construis 2 objets de suite avec les mêmes paramètres, ils auront pas le même hash correct ?
-->benou : je savais, mais justement, comme je savais pas lequel choisir, g parlé de set, comme ca tlm voit de quoi je veux parler...le treeSet faudrait que je regarde parce que la finalité de mes 3 vector c d'etre mis dans dans une GUI sous forme d'arbre...
Marsh Posté le 11-06-2004 à 11:34:08
Jubijub a écrit : j'ai redéfini equals et hashcode pour que ca porte que sur les champs que je veux... |
en quoi ca arrange ton problème de tes 3 façons de voir l'égalité de tes objets dans tes Set ?
Jubijub a écrit : |
ben si tu rédéfinis le hashCode correcetment non. Par contre si tu ne le redéfinis pas (que tu laisses l'implémentation issue de Object), là oui, ils seront différents.
Marsh Posté le 11-06-2004 à 11:41:55
--> comment le rédéfinir proprement ? (je sais pas calculer une fonction de hash moi...)
--> en fait dans mes 3 catégories d'objets, je ne dois comparer que des objets de même catégorie... que des platforms entre elles, que des mobiles entre eux, etc...
==> le treeSet a l'air de faire ce que je veux en fait...pis ca me sera utile pour les arbres après...le fait est que je dois faire que mes objets implémentent comparable...et je sais pas trop comment redéfinir le compareTo, sachant que je vois pas comment ordonner des objets comme ca... (peut etre que le int renvoyé par le hash est une solution, mais je dois etre certain que mon hash renvoit toujours le même int sur 2 objets identiques...ce dont je suis pas sur avec l'implémentation actuelle
edit : mes champs à comparer étant des String, le hash de String se base sur le contenu de la String, et pas l'adresse mémoire...il en résulte que normalement :
Code :
|
doit renvoyer true...ce qui serait pas le cas avec l'implémentation d'objet, car toto et tutu n'ont normalement pas les même adresses mémoires (à moins que la JVM détecte que c la même String qui est passée en paramètre,et que donc il fasse pointer toto et tutu sur la même adresse mémoire...mais je pense que tlm a compris ce que je voulais dire)
Marsh Posté le 11-06-2004 à 11:48:10
Jubijub a écrit : --> comment le rédéfinir proprement ? (je sais pas calculer une fonction de hash moi...) |
http://forum.hardware.fr/forum2.ph [...] 486&cat=10
Jubijub a écrit : |
Non. Ca c'est seulement si tu n'utilises pas de Comparator. Si tu utilises un Comparator, tu n'est pas obligé.
Dans ton cas, l'ordre n'a pas vraiment d'importance. Ce qui t'intéresse c'est l'égalité (quand ca retourne 0). => quand c'est pas égale, ordone les sur un truc à la con genre un nom ou un truc comme ca (return name.compareTo(lAutreObjet.name). Tu es obligé d'avoir un ordonnacement réel de façon à assurer que si compare(a,b) < 0, compare(b,a) > 0. Sinon, ton TreeSet risque de merder méchament. => si tu te bases sur un ordre déjà fait (celui des String) ca ira
sinon, y a une grosse faute dans l'implémentation du hashCode que tu a montré : les hashCodes de 2 objets égaux doit être égaux. C'est la seule à respecter, mais dans ton cas c'est faux
Marsh Posté le 11-06-2004 à 11:51:17
Jubijub a écrit : je pense que tlm a compris ce que je voulais dire) |
non
Tu voulais en venir où en disant ca ?
edit : et oui, la JVM utilisera le même objet String pour toto et tutu.
Marsh Posté le 11-06-2004 à 12:07:18
benou a écrit : n'importe quoi |
euh qu'est-ce qui est n'importe quoi ?
sans generics, à tous les coups tu vas oublier de wrapper ton objet.
Marsh Posté le 11-06-2004 à 12:12:05
Je v réexpliquer mon pb simplement, que tlm comprenne (parce que g pas été clair)
G trois listes (je dis liste parce que g pas encore fixé quelle implémentation j'allais choisir).
Une liste de Plaform, une liste de Mobile, et une liste d'Emulateur.
G un peu designé ca comme si ct une base de données avec 3 tables.
Une platform peut lister plusieurs mobiles.
Un mobile ne peut etre contenu que par une et une seule platform
Un mobile n'a qu'un et un seul émulateur.
Un émulateur peut etre référencé par plusieurs mobiles.
Une platform contient :
Code :
|
A noter : l'identifier est la "clé", et est une String formattée d'une manière très précise. Il ne peut y avoir 2 platforms avec le même identifier
C à peu près pareil pour Mobile. La clé est le nom (String), et là aussi il ne peut pas y avoir 2 mobiles avec le même nom.
Pour l'émulateur, l'identifiant c le couple nom + version (String aussi)...
Pour l'instant, mes problèmes sont :
==> c en cours, c le truc de nraynaud qui m'a fait penser que je me ferais moins chier à réimplémenter equals pour qu'il teste les attributs que je veux qu'à les tester moi même à chaque fois.
---------> g pas compris pkoi tu dis que g une faute d'implémentation en redifinissant mon hash comme ca :
d'après mon equals, 2 émus sont égaux si ils ont le même nom et la même version....
nom et version étant des String, et l'algo de hash des String étant basé sur leur contenu, 2 objets ayant le même nom et la même version auront forcément le même hash, donc le contrat est respecté non ?
--> dans mon cas equals veut pas dire que tt les attributs de l'objet sont identiques, mais juste ceux représentant la clé...
Marsh Posté le 11-06-2004 à 12:19:03
the real moins moins a écrit : euh qu'est-ce qui est n'importe quoi ? |
ça va pêter à l'insertion, donc aussi tôt que possible.
Marsh Posté le 11-06-2004 à 12:20:15
euh ouais, au runtime quoi.
suffit que tu l'aies oublier dans un cas à la cas et que tu fasses pas de testunitaires assez complet et pan
bref. sapu.
tu redefinis l'equals de ton objet si c suffisant, sinon t'utilises le Set auqueul tu peux passer un comparator et voilà .|
Marsh Posté le 11-06-2004 à 12:43:19
the real moins moins a écrit : euh ouais, au runtime quoi. |
et alors ? c'est exactement pareil avec des objets normaux qu'on caste à la sortie.
Le paranos peuvent wrapper la collection pour la typer s'il veulent.
Marsh Posté le 11-06-2004 à 12:45:15
nraynaud a écrit : et alors ? c'est exactement pareil avec des objets normaux qu'on caste à la sortie. |
euh sauf que dans ta logique bizness tu utilises des Machin mais que faut pas oublier que dans le foutu cas de merde ou tu vaq les foutre dans un Set faut les wrapper désolé mais
equals ou Comparator, tres bien , et c fait pour ça. le coup du wrapper c'est bricolo et c'est error-prone
Marsh Posté le 11-06-2004 à 12:54:14
the real moins moins a écrit : euh sauf que dans ta logique bizness tu utilises des Machin mais que faut pas oublier que dans le foutu cas de merde ou tu vaq les foutre dans un Set faut les wrapper désolé mais |
Des fois t'es lourd, y'a rien qui t'oblige à exposer la chose à l'utilisateur je te dis !
Alors que redéfinir equals et forcément visible par l'utilisateur et utiliser un arbre change la complexité.
Marsh Posté le 11-06-2004 à 13:45:01
bah oui, les TreeSet son pluggable, c'est plus facile, mais tu as une complexité plus grande.
Marsh Posté le 11-06-2004 à 14:25:34
"pluggable" tu peux y "brancher" ton propre comparateur. Pour comparer sur d'autres critères que le critère par défaut de l'objet.
heu non, il n'y a jamais de get dans un tree set, tu peux y ajouter des choses, les enlever, voir si une chose est dedans ou itérer sur ses éléments, c'est tout.
tu voudrait lui passer quoi comme argument à ton get ?
Marsh Posté le 11-06-2004 à 14:26:56
the real moins moins a écrit : euh qu'est-ce qui est n'importe quoi ? |
Si tu l'utilise mal => si tu sais pas coder => si tu sais pas coder, tu ferras tout un tat d'autres erreurs...
On a vécu avant qu'il y ait les générics hein
Marsh Posté le 11-06-2004 à 14:31:48
nraynaud a écrit : "pluggable" tu peux y "brancher" ton propre comparateur. Pour comparer sur d'autres critères que le critère par défaut de l'objet. |
get(i)
--> cad pouvoir récupérer l'élément à l'index i facilement, sans devoir me taper tt la liste pour le retrouver...
ou pouvoir facilement mouliner à travers tt la liste pour trouver un élément qui correspond à ce que je cherche...
Marsh Posté le 11-06-2004 à 14:33:07
benou a écrit : Si tu l'utilise mal => si tu sais pas coder => si tu sais pas coder, tu ferras tout un tat d'autres erreurs... |
ouais on a meme fait du c
Marsh Posté le 11-06-2004 à 14:33:25
Jubijub a écrit : |
1) tu n'a aucune garantie d'ordre dans un set, il faut utiliser une List pour ça
2)pour mouliner, y'a Iterator.
Marsh Posté le 11-06-2004 à 14:35:35
the real moins moins a écrit : ouais on a meme fait du c |
( )
Marsh Posté le 11-06-2004 à 14:40:08
Jubijub a écrit : 1) je m'en fou de l'ordre, je veux surtout interdire la duplication...ce qui est la philo du set à la base |
1) bah c'est interdit automatiquelent, je vois pas pourquoi tu veux faire ça toi-même. si tu tentes d'insérer 2 fois le même objet, la seconde tentative va échouer.
2) ???? c'est fait pour ça et uniquement pour ça ???
Marsh Posté le 11-06-2004 à 14:42:00
2) je comprends pas l'intéret de la chose alors qu'un bete
Code :
|
te permet de faire une itération, avec le pas que tu veux, et en faisant tt ce que tu veux...y'a surement une raison pour laquelle un itérator existe, mais je vois pas laquelle...
Marsh Posté le 11-06-2004 à 14:43:16
Jubijub a écrit : y'a surement une raison pour laquelle un itérator existe, mais je vois pas laquelle... |
pour itérer ?
pour uniformiser les méthodes d'itération ?
pour permettre un controle sur la cohérence de l'itération ? (non-modification de l'objet itéré)
et j'ai oublié le plus important : pour virtualiser ce sur quoi tu itères ? (peut importe l'objet qui est derrière, tu peux récupérer les objet qui le compose)
Marsh Posté le 11-06-2004 à 14:52:17
y'a une implémentation tt faite ou faut la faire soit même ? (c qu'une interface visiblement, et je y'a pas de know implementing classes)
g rien dit, ca s'obtient tt seul avec le iterator() de la collection.
Marsh Posté le 11-06-2004 à 15:47:38
la règle d'or est objets égaux => hashCodes identiques (mais pas l'inverse, j'y reviens pas).
Or ton égalité est insensible à la casse alors que le hashcode si.
pour simplifier tu aurais "TuTL".aqualsIgnorecase("tutl" )
mais "TuTL".hashCode() != "tutl".hashCode().
ça ne fonctionne pas. la seule solution c'est de tout convertir en minuscules ou en majuscules et de faire le equals() et le hashCode() dessus.
Marsh Posté le 11-06-2004 à 15:57:31
c ténu comme détail, mais bien vu
en plus je force déjà que tt soit en majuscule quand c du texte...donc un equals me suffira
le ignoreCase c l'habitude,en général c plutot souhaitable que TUTU = tutu = TuTu, surtout dans le cas d'entrée utilisateur.
donc ca ca doit marcher
Code :
|
Marsh Posté le 11-06-2004 à 20:20:47
oui.
Mais bon, comme on te l'as déjà dit, c'est pas top de redéfinir le equals pour des raisons de faciliter. Redéfinir equals, ca doit vraiment avoir un sens pour ton objet.
Marsh Posté le 10-06-2004 à 17:59:35
http://java.sun.com/j2se/1.4.2/doc [...] ng.Object)
D'après la javadoc, je comprends que ca utilise la méthode equals de l'implémentation de collection qu'on utilise...
J'aimerais pouvoir modifier ce comportement...
En gros g des listes...mais pour mon appli, 2 objets peuvent être égaux sans que equals renvoit true et sans que leur hashcode soit le même...
par ex un émulateur est repéré par son nom et son numéro de version...deux emu ne peuvent partager le même couple (nom,version), même si les autres infos que contiennent les émus sont différentes...
Mon soucis vient de là : si par ex on renomme un émulateur, je veux etre sur qu'avec le nouveau nom il n'y aura pas 2 émus identiques (je teste que ce soit pas le cas à la création, je voudrais pouvoir le vérifier à la modif...)
Pour l'instant mes listes sont des Vector, à cause de la synchronisation...je me demande si il y a une méthode autre que sousclasser une des classes implémentant set...et redéfinir la méthode equals...
le truc super merdique qui fait que g pas trop envie, c que je gère 3 listes, et que chacune des listes contient des objets qui peuvent être égaux selon des conditions différentes...
J'avais pensé aussi ajouter l'objet, parser la liste en vérifier que index(objet) == lastIndex(objet) (en gros il est présent qu'une fois) et lancer une exception sinon, et rétablir l'objet dans son ancienne forme...
vous en pensez quoi ?
---------------
Jubi Photos : Flickr - 500px