IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Collection et Stream Java Discussion :

Objet présent dans un Set


Sujet :

Collection et Stream Java

  1. #1
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut Objet présent dans un Set
    Bonjour,

    Ma question est philosiphique... mais aussi utile à moi

    La classe (import java.util.)Set est un ensemble d'objets unique dans le sens Object.equals(Object) du terme. Cette classe est bien utile dans ma question... Elle permet de faire un ajout d'élément comme pour une Map :
    Set.add(Object) "<=>" Map.put(Object.hashCode(),Object) -je laisse là les puristes interloqués : les guillemets me permettent de dire l'équivalence.

    Bon, là c'est bien, c'est pratique et c'est rapide. Mais c'est là que je pose la question -enfin !... Comment faire pour lire un objet dans le Set ? Je veux dire par là, qu'il n'y a pas de méthode pour retourner un objet présent dans le Set, s'il y est déjà... un genre de Set.get(Object) qui retourne l'objet équivalent dans le Set (celui qui est unique). Pourtant, quand je fait un Set.contains(Object)... l'objet est bien trouvé... Mais pas retourner si je le veux.

    Vous allez me dire... "Tu dois utiliser le .toArray() ou le .iterator() -etc. pour le trouver ton objet !". Et vous avez raison. Mais je perd tout le bénifice du hachage dans ce cas. Je dois parcourir un à un les éléments et faire le teste d'égalité.

    Je peux aussi utiliser une Map, avec, à chaque ajout : Map.add(object.hashCode(),object)... Mais c'est lourd et pleins de risques...

    Je peux aussi une classe MapWrapper héritant d'une Map et qui redéfini la méthode add...

    Vous faites comment ? Vous feriez quoi ?

    Merci.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Set.add(Object) "<=>" Map.put(Object.hashCode(),Object) -je laisse là les puristes interloqués : les guillemets me permettent de dire l'équivalence.
    Ce n'est pas équivalent : si tu as deux objets qui ont le même hashcode mais qui ne sont pas égaux, tu écrase l'un avec l'autre.

    Pour faire ce que tu veux, la meilleur solution est d'utiliser une map et de faire put(object, object)

  3. #3
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Citation Envoyé par the-gtm
    Ce n'est pas équivalent : si tu as deux objets qui ont le même hashcode mais qui ne sont pas égaux, tu écrase l'un avec l'autre.
    FAUX... FAUX.... FAUX.... SI vous écrivez un objet je vous conseil de bien voir la JSF et de redéfinir le hasCode() ET equals()... Relit la JSL... il faut hacheCode() ET equals()==true, sinon, les deux objets ne sont pas les mêmes.

    Mais, bon, ta réponse est dans ma question...
    1) J'ai pas demendé une citation de la JSL et je vais pas la détailler pour avoir utiliser "<=>"... surtout que pour ma question, mettre "<=>", c'est suffisant;

    2) Je sais qu'il faut utiliser une Map,... Mais ça me dérange de faire se que le Set fait presque .. .tout seul C'est pas l'esprit du Java cela...

    Il y a surement un java-ist qui c'est posé la question, et à trouver une réponse...

    Merci de votre attention.

    Laurent

  4. #4
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    J'avais déjà posté ce genre de question, où je voulais séparer un objet en "clé" et "le reste", où la clé déterminait le hashCode et le equals, et où à partir de la clé uniquement on pouvait récupérer l'objet complet...

    Je ne retrouve plus le post...

    La solution à retenir (que j'avais retenue) était de le faire "à la main"...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class UneClasse {
        static class Key {
            private String nom1;
            private String nom2;
            public boolean equals(Object o) { ... }
            public int hashCode() { ... }
        }
        private Key key;
        private String details;
        ...
    }
    Ensuite tu peux faire une classe qui encapsule une Map
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Map<UneClasse.Key,UneClasse> map;
    avec une méthode register(UneClasse uneClasse) qui fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void register(UneClasse uneClasse) {
        map.put(uneClasse.getKey(), uneClasse);
    }
    Et une méthode pour récupérer l'objet à partir de sa clé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void get(UneClasse.Key key) {
        return map.get(key);
    }
    J'avais utilisé cela pour faire un compilateur java -> assembleur pour les cours, en particulier pour les "Methods".
    Une méthode ça a une clé : le nom de la méthode et le type des paramètres.
    Et ça a des informations complémentaires : le type de retour.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    361
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 361
    Points : 429
    Points
    429
    Par défaut
    Citation Envoyé par the-gtm
    si tu as deux objets qui ont le même hashcode mais qui ne sont pas égaux, tu écrase l'un avec l'autre.
    Citation Envoyé par Lorantus
    FAUX... FAUX.... FAUX....
    Je ne vois pas en quoi c'est faux...

    Si tu fais map.put(hashCode, objet), pour 2 hashCode identiques, le premier objet sera écrasé ...
    Et ça même si les deux objets sont différents, puisqu'ils peuvent avoir le même hash.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Normalement a.equals(b) => a.hashcode() == b.hashcode() mais l'inverse n'est pas vrai (Sinon pourquoi faire deux méthode?). Donc tu peux très bien faire une méthode hashcode qui renvoie toujours 0, ça réduit l'interêt des HashMap mais c'est parfaitement valide.

    Après tu peux avoir des objets pour lesquels equals est équivalent à hashcode mais c'est dangereux de compter la dessus. Si quelqu'un passe derrière toi sur ton code il va avoir du mal à comprendre.

  7. #7
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Bonjour,

    J'aimerai bien que l'on ne s'égare par trop:
    "J'ai pas ouvert ce thread pour faire une discussion sur le hashCode() ou les caractèristiques de la Map... J'ai juste ouvert ce thread pour demander comment profiter des perfomances de Map avec un Set, car le Set permet par le hashCode() + equals() (!!!!) de gérer des ensembles d'objets uniques très rapidement. Contrairement à une List qui demande des iterations pour trouver ce qui nous interesse."

    Pour le moment,il n'y a que "Room" qui m'a répondu, sans pour autant montrer qu'il sait pleins de choses...: le forum, c'est pas remplir un mal de reconnaissance, c'est pour aider et partager.

    Il semble que se soit la meillieur solution, aujourd'hui, d'encapsuler une Map dans une classe enveloppe. Ce qui est dommage c'est que je me retrouve à créer une perso-API que je ne suis pas le seul à utiliser

    Merci.

    Laurent

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    361
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 361
    Points : 429
    Points
    429
    Par défaut
    Citation Envoyé par Lorantus
    Ce qui est dommage c'est que je me retrouve à créer une perso-API que je ne suis pas le seul à utiliser
    Il y a peut être quelque chose comme ça dans commons collections ?

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Je vois pas trop où le problème avec la solution que je proposais : utiliser une map

  10. #10
    Rédacteur
    Avatar de Hikage
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 177
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 177
    Points : 6 301
    Points
    6 301
    Par défaut
    Citation Envoyé par Lorantus
    Bonjour,


    Bon, là c'est bien, c'est pratique et c'est rapide. Mais c'est là que je pose la question -enfin !... Comment faire pour lire un objet dans le Set ? Je veux dire par là, qu'il n'y a pas de méthode pour retourner un objet présent dans le Set, s'il y est déjà... un genre de Set.get(Object) qui retourne l'objet équivalent dans le Set (celui qui est unique). Pourtant, quand je fait un Set.contains(Object)... l'objet est bien trouvé... Mais pas retourner si je le veux.
    D'un autre coté, si tu fais un Set.contains(Object) .. tu dois déja avoir l'objet que tu désire ( vu que tu le passe en paramètre) , et donc je vois pas l'intéret de "rechercher" dans le Set ?

    Au pire, tu fais une méthode static "public static Object getFromSet(Set, Object)" qui te retourne null si l'objet n'est pas dans le set et qui te retourne l'objet si c'est le cas.

    Ou alors j'ai pas saisi le problème

  11. #11
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Dans un Set, j'ai en ensemble d'objets uniques (au sens equals()), et c'est se que je veux. Mais j'aimerais pouvoir reprendre cet objet, en soumettant à mon Set un objet équivalent (au sens equals()) à celui que je voudrais:

    si Set.trouveObjetEgal(objet_a_rechercher) alors
    retourne objet_egale_a_objet_a_rechercher
    sinon
    retourn null
    Au pire, tu fais une méthode static "public static Object getFromSet(Set, Object)" qui te retourne null si l'objet n'est pas dans le set et qui te retourne l'objet si c'est le cas.
    Oui.... Mais je dois parcourir mes éléments un à un pour trouver le bon, comme pour un List, et je perd de bénéfice d'une table de hachage. Sur les petites listes, c'est "pas visible", mais sur 30 000 élements, 5 fois de suite, cela explose les temps de traitements (et si tu ajoute un String.equals(String) dans le test d'égalité... C'est plus une explosion, c'est BOOOOM .


    Faire pour chaque recherche d'élément :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int index=list.indexOf(objet);
    Object resultat=null;
    if(!index<0)
     resultat=list.get(index);
    mais les temps explosent contrairement à une table de hachage.

    Je cherche donc juste à savoir si un tel type d'objet existe via une API standard, afin de ne pas en créer une...

    Merci de votre collaboration.

  12. #12
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Au risque de paraître lourd, pourquoi pas une Map ?

  13. #13
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Au risque de paraître lourd, pourquoi pas une Map ?
    Est une solution car il y a la table de hachage, de plus, on peut avoir l'objet que l'on souhaite... C'est ce dont nous avons parlé au début du thread...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Map.put(objet.hashCode(),objet);  //Restons simple
    Map.get(objet.hashCode());         //Sans être en 1.5 ....
    Ce qui m'ennuis, c'est le devoir faire le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    map.put(objet.hashCode(),objet)
    alors que si je prend un Set, il me faut ajouter le "get"... uniquement. Mais il faut l'ajouter.

    Je pousse le thread car j'ai vraiment de plancher là dessus : c'est pas la 1ere fois que j'ai besoin de cela... Avant je faisais avec une Map ou une List, en fonction des performences voulus...

    Aujourd'hui, je voudrais faire mieux et je suis pas le seul dans ce cas, je pense.

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    System.out.println("2L".hashCode());
    System.out.println("3-".hashCode());
    Marrant non ?

    Donc il faut faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Map.put(objet, objet);
    Map.get(objet);
    Ce qui n'est pas très compliqué

  15. #15
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Pire !

    Je tombe de nouveau sur la solution de "Room"...

  16. #16
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par the-gtm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    System.out.println("2L".hashCode());
    System.out.println("3-".hashCode());
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    System.out.println("XxXxXxXx".hashCode());
    System.out.println("YYYYYYYY".hashCode());

  17. #17
    Membre averti
    Inscrit en
    Juin 2003
    Messages
    292
    Détails du profil
    Informations forums :
    Inscription : Juin 2003
    Messages : 292
    Points : 317
    Points
    317
    Par défaut
    Salut,
    Reponse a Lorantus "Comment faire pour lire un objet dans le Set?....Set.get(Object)"

    C est le design qu ont choisis chez Sun, ils trouvent que c est un truc tres facile a faire et c est meilleur qu ils laissent ca a l utilisateur de predir son resultat.
    ca c est la doc Java Collections API Design FAQ
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Why didn't you provide a "Predicate" interface, and related methods (e.g., a method to find the first element in the Collection satisfying the predicate)?
     
    It's easy to implement this functionality atop Iterators, and the resulting code may actually look cleaner as the user can inline the predicate. Thus, it's not clear whether this facility pulls its weight. It could be added to the Collections class at a later date (implemented atop Iterator), if it's deemed useful.
    encore un dernier trucs sur Set <=> Map ceci aussi cest une question de design
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
       1. Why doesn't Map extend Collection?
     
          This was by design. We feel that mappings are not collections and collections are not mappings. Thus, it makes little sense for Map to extend the Collection interface (or vice versa).
     
          If a Map is a Collection, what are the elements? The only reasonable answer is "Key-value pairs", but this provides a very limited (and not particularly useful) Map abstraction. You can't ask what value a given key maps to, nor can you delete the entry for a given key without knowing what value it maps to.
     
          Collection could be made to extend Map, but this raises the question: what are the keys? There's no really satisfactory answer, and forcing one leads to an unnatural interface.
     
          Maps can be viewed as Collections (of keys, values, or pairs), and this fact is reflected in the three "Collection view operations" on Maps (keySet, entrySet, and values). While it is, in principle, possible to view a List as a Map mapping indices to elements, this has the nasty property that deleting an element from the List changes the Key associated with every element before the deleted element. That's why we don't have a map view operation on Lists.

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Citation Envoyé par Lorantus
    Pire !

    Je tombe de nouveau sur la solution de "Room"...
    Une ligne de code pour mettre un objet, une autre pour le retrouver, un temps de recherche en log(n), tu vas avoir du mal à trouver mieux... Je ne vois toujours pas où est le problème.

  19. #19
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Une ligne de code pour mettre un objet, une autre pour le retrouver, un temps de recherche en log(n), tu vas avoir du mal à trouver mieux... Je ne vois toujours pas où est le problème.
    C'est qu'il faut écrire dans les paramètres d'appel la clef ! Alors qu'elle se trouve dans l'objet à mémoriser. C'est un peu lourd et pas très "save". (avant de me dire, "tu peux utiliser une fonction pour chaque appel" , lisons la suite )

    jhaythem aura donner le coup de grâce au thread -si je peux dire ainsi

    Room a donné la solution la plus approchante. Me reste à faire une interface et un abstract pour gérer tout cela simplement, et pouvoir l'étendre sur mes besoins .

    Merci de votre participation.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 30/12/2011, 15h44
  2. Réponses: 1
    Dernier message: 11/07/2011, 15h59
  3. Réponses: 5
    Dernier message: 14/09/2010, 18h11
  4. Stocker une liste d'objets personnalisés dans les settings
    Par laville dans le forum Général Dotnet
    Réponses: 12
    Dernier message: 13/12/2007, 12h14
  5. Enregistrement d'objet persos dans les settings
    Par skylvl dans le forum VB.NET
    Réponses: 1
    Dernier message: 07/03/2007, 15h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo