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 :

[TreeSet] Action sur Element lorsque Doublon


Sujet :

Collection et Stream Java

  1. #1
    Membre habitué
    Avatar de CPI_en_mousse
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2006
    Messages
    332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 332
    Points : 168
    Points
    168
    Par défaut [TreeSet] Action sur Element lorsque Doublon
    Bonjour à tous,

    Je souhaiterais qu'un Boolean contenu dans l'objet du TreeSet change d'état lorsque j'essaie d'ajouter un objet identique.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    public class CommuneDto implements Comparable<CommuneDto> {
        private String code;
        private String libelle;
        private Boolean indicActif;
     
    @Override
        public boolean equals(Object o) {
            if (o == null || getClass() != o.getClass()){
                return false;
            }
     
            CommuneDto commune = (CommuneDto) o;
            if (this.getCode().equals(commune.getCode()) && this.getLibelle().equals(commune.getLibelle())) {
                return true;
            }
     
            return false;
        }
     
        @Override
        public int hashCode() {
            return code.hashCode() + libelle.hashCode();
        }
     
        /* (non-Javadoc)
         * @see java.lang.Comparable#compareTo(java.lang.Object)
         */
        @Override
        public int compareTo(CommuneDto o) {
            return this.getCode().compareTo(o.getCode());
     
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Set listeCommune = new TreeSet<CommuneDto>();
    listeCommune.add(competenceGeographiqueService.chargerCommune(codeCommune));
    Je ne sais pas si je suis très clair, lorsque j'ajoute une commune à mon treeSet et que cette commune existe déjà dans ce treeSet, je voudrais que indicActif soit vrai.
    Je ne vois pas comment faire avec un treeSet.
    J'avais pensé à inclure la mise à jour du boolean dans les methode hashCode ou equals que j'ai redéfini. Est une bonne idée?
    Si c'est pas possible, je passerai par une arrayList mais je devrai gérer les doublons à la main.

    Si quelqu'un à une idée sur comment faire....

    Merci pour vos réponses
    Tout à une fin, sauf le saucisson qui en as 2.
    -----------------

  2. #2
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par CPI_en_mousse Voir le message
    J'avais pensé à inclure la mise à jour du boolean dans les methode hashCode ou equals que j'ai redéfini. Est une bonne idée?
    Non, pas bonne idée !

    Pourquoi ne pas plutôt utiliser HashMap en plus?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Set listeCommune = new TreeSet<CommuneDto>();
    CommuneDto myCommune = competenceGeographiqueService.chargerCommune(codeCommune);
    if (listeCommune.add(myCommune)){
         mapCommunes.put(codeCommune, myCommune);
    } else {
         mapCommunes.get(codeCommune).setIndicActif(Boolean.TRUE);
    }
    Ca implique juste d'avoir une HashMap<String, CommuneDto> qui stocke les liens vers les instances de commune dans ton TreeSet, et de créer un setter de indicActif


    (la méthode add renvoie true seulement si l'élement a été ajouté au Set)
    Je ne suis pas mort, j'ai du travail !

  3. #3
    Membre habitué
    Avatar de CPI_en_mousse
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2006
    Messages
    332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 332
    Points : 168
    Points
    168
    Par défaut
    bon au final j'ai fait quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
            if (!competenceGeographiqueBacking.getSetCommunePersonne().add(communeAjout)) {            
                competenceGeographiqueBacking.getSetCommunePersonne().forEach(commune -> {
                    if (commune.equals(communeAjout)) {
                        commune.setIndicActif(Boolean.TRUE);
                    }
                });
            }

    Merci pour ton aide eulbobo.
    Tout à une fin, sauf le saucisson qui en as 2.
    -----------------

  4. #4
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    C'est une solution qui marche aussi !
    J'espère juste que tu n'auras pas trop d'éléments dans ton set parce le parcourir en entier à chaque fois quand un seul élément doit être mis à jour, ça peut vite être long.
    Je ne suis pas mort, j'ai du travail !

  5. #5
    Membre habitué
    Avatar de CPI_en_mousse
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2006
    Messages
    332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 332
    Points : 168
    Points
    168
    Par défaut
    du coup j'ai optimisé ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
            Predicate<CommuneDto> predicate = commune -> commune.equals(communeAjout);
            if (!competenceGeographiqueBacking.getSetCommunePersonne().add(communeAjout)) {
                competenceGeographiqueBacking.getSetCommunePersonne().stream().filter(predicate).forEach(commune -> {
                    if (commune.equals(communeAjout)) {
                        commune.setIndicActif(Boolean.TRUE);
                    }
                });
            }
    Tout à une fin, sauf le saucisson qui en as 2.
    -----------------

  6. #6
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut


    Y'a pas à dire, c'est beau ce qu'on peut faire en Java8 !
    Je ne suis pas mort, j'ai du travail !

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Jvois pas bien ce que ça apporte par rapport à la précédente solution par contre.

    Ça optimise rien du tout, ça met juste la vérification dans un filter(), ... et ça revérifie encore derrière pour les éléments qui ont passé le filter() -_-°.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    J'imagine naïvement que le stream est plus efficace qu'une simple itération. Et comme on est dans un TreeSet, le foreach final n'aura qu'un élément à modifier (puisque le prédicat est sur la méthode equals)

    Allez, ça vaut bien un petit benchmark pour voir !
    Je ne suis pas mort, j'ai du travail !

  9. #9
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Le stream n'est pas spécialement plus efficace qu'une simple itération. stream et itération doivent tous les deux s'occuper de tous les éléments, dans le même ordre.
    On peut le rendre plus efficace derrière, comme s'arrêter après un élément, mais là ce n'est pas le cas.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    import java.util.TreeSet;
    import java.util.function.Predicate;
     
    /**
     *
     */
    public class MyTestClass {
     
    	/**
             * @param args
             */
    	public static void main(String[] args) {
     
    		// initialisation
    		TreeSet<MyInternal> tree = new TreeSet<>();
    		for (int i = 0; i < 100_000; i++) {
    			tree.add(new MyInternal(i, "" + i));
    		}
     
    		MyInternal myInternalTest = new MyInternal(200, "" + 200);
     
    		Predicate<MyInternal> predicate = elt -> elt.equals(myInternalTest);
     
    		// filtre par prédicat
    		long begin = System.currentTimeMillis();
    		tree.stream().filter(predicate).forEach(elt -> {
    			System.out.println("modification !");
    		});
    		System.out.println("Execution avec filter en " + (System.currentTimeMillis() - begin) + " ms");
     
    		begin = System.currentTimeMillis();
    		// pas de filter
    		tree.stream().forEach(elt -> {
    			if (elt.equals(myInternalTest)) {
    				System.out.println("modification !");
                }
    		});
    		System.out.println("Execution sans filter en " + (System.currentTimeMillis() - begin) + " ms");
     
    		begin = System.currentTimeMillis();
    		// boucle simple
    		for (MyInternal elt : tree){
    			if (elt.equals(myInternalTest)) {
    				System.out.println("modification !");
                }
    		}
    		System.out.println("Execution boucle en " + (System.currentTimeMillis() - begin) + " ms");
     
    		begin = System.currentTimeMillis();
    		// boucle simple iterator
    		Iterator<MyInternal> iter = tree.iterator();
    		while (iter.hasNext()){
    			if (iter.next().equals(myInternalTest)) {
    				System.out.println("modification !");
                }
    		}
    		System.out.println("Execution iterator en " + (System.currentTimeMillis() - begin) + " ms");
     
    	}
     
    	static class MyInternal implements Comparable<MyInternal> {
    		int myInt = 0;
    		String myStr = "";
     
    		MyInternal(int i, String s) {
    			myInt = i;
    			myStr = s;
    		}
     
    		@Override
    		public int hashCode() {
    			final int prime = 31;
    			int result = 1;
    			result = prime * result + myInt;
    			result = prime * result + ((myStr == null) ? 0 : myStr.hashCode());
    			return result;
    		}
     
    		@Override
    		public boolean equals(Object obj) {
    			if (this == obj)
    				return true;
    			if (obj == null)
    				return false;
    			if (getClass() != obj.getClass())
    				return false;
    			MyInternal other = (MyInternal) obj;
    			if (myInt != other.myInt)
    				return false;
    			if (myStr == null) {
    				if (other.myStr != null)
    					return false;
    			} else if (!myStr.equals(other.myStr))
    				return false;
    			return true;
    		}
     
    		@Override
    		public int compareTo(MyInternal o) {
    			return (myInt < o.myInt) ? -1 : ((myInt == o.myInt) ? 0 : 1);
    		}
     
    	}
    }
    Résultats du test :
    Execution avec filter en 12 ms
    Execution sans filter en 6 ms
    Execution boucle en 7 ms
    Execution iterator en 8 ms

    Donc effectivement le filtre sur stream et dans notre cas moins efficace qu'un parcours brut avec vérification à chaque fois

    (je me coucherai moins con ce soir)


    Tester avec un TreeSet de 1 million d'éléments :
    Execution avec filter en 31 ms
    Execution sans filter en 27 ms
    Execution boucle en 30 ms
    Execution iterator en 28 ms (oui, j'ai rajouté le parcours avec Iterateur)

    Bref, ça se vaut sur les très grosses maps...
    Je ne suis pas mort, j'ai du travail !

  11. #11
    Membre habitué
    Avatar de CPI_en_mousse
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2006
    Messages
    332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 332
    Points : 168
    Points
    168
    Par défaut
    Bon ben du coup, je repasse à la 1ere solution.

    Merci beaucoup....
    Tout à une fin, sauf le saucisson qui en as 2.
    -----------------

  12. #12
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par eulbobo Voir le message
    Résultats du test :
    Attention c'est biasé tout ça. C'est pas facile d'écrire des benchmarks.

    Là le premier test se tape toute l'optimisation JIT, et les suivants en profitent.
    Si tu testes dans un autre ordre, tu obtiens des résultats différents. Et si tu mets plus d'éléments, le temps de faire l'optimisation JIT compte moins.

    Citation Envoyé par eulbobo Voir le message
    Bref, ça se vaut sur les très grosses maps...
    Voilà. J'essayais pas de dire qu'une était moins efficace que l'autre, car la différence ne casse pas trois pattes à un canard.

    Je disais que la tentative d'optimiser (et le code supplémentaire qu'elle contient) n'optimise rien du tout et donc ne justifie pas de compliquer le code.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

Discussions similaires

  1. [XL-2007] Action sur les doublons ?
    Par neox_mimi dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 27/10/2010, 14h39
  2. Réponses: 3
    Dernier message: 06/04/2010, 11h56
  3. [intput] action par défaut lorsqu'on appuit sur "Enter&
    Par pmartin8 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 25/10/2005, 18h45
  4. Pb d'action sur un clip
    Par bencasp dans le forum Flash
    Réponses: 4
    Dernier message: 22/10/2003, 17h11
  5. [Flash MX] Action sur un bouton
    Par WriteLN dans le forum Flash
    Réponses: 9
    Dernier message: 20/10/2003, 14h01

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