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 :

ArrayList et doublons, cas vraiment particulier


Sujet :

Collection et Stream Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Par défaut ArrayList et doublons, cas vraiment particulier
    Bonsoir,

    Je suis en train de parser des fichiers contenant des informations
    qui iront en base un peu plus tard, et j'ai tellement peur de mes
    collègues que je suis en train de verrouiller le plus possible ce module
    d'importation...
    Bref, j'ai une contrainte forte sur la table en question, et j'essaye de
    faire en sorte que les données que je vais lui envoyer soient les plus
    propres possibles!

    J'aurais besoin de conseils quant à la recherche et destruction de
    tous les doublons, afin de ne garder que ce qui n'a aucun
    doublon. En gros, j'ai un fichier

    date1,valeurX
    date2,valeurX
    ...
    dateN,valeurX

    mon conteneur est
    mon conteneur{
    Timestamp date;
    Float valeur
    }

    Si il y a un doute car la date est en doublon sur une ou plusieurs
    lignes, j'ai le devoir d'enlever le/les doublon(s) ET la première
    donnée qui serait "doublonnée", je ne suis pas sur d'être plus clair

    Donc il y aurait bien l'utilisation d'un Set particulier (HashSet il
    me semble) mais ce dernier ne résoudra pas vraiment mon problème.
    La contrainte est sur la date bien entendu.

    J'ai peur de ré-inventer la roue, et c'est pourtant ce que je suis
    en train de faire... des idées?

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Par défaut
    Typiquement la solution apportée ici par vincent63:
    http://www.developpez.net/forums/d64...ever-doublons/

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    System.err.println("Début");
    ArrayList arrayList = new ArrayList();
    arrayList.add("a");
    arrayList.add("b");
    arrayList.add("c");
    arrayList.add("d");
    arrayList.add("a");
    System.err.println(arrayList);
    System.err.println("On utilise des ensembles");
    Set set = new TreeSet();
    set.addAll(arrayList);
    System.err.println(set);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Début
    [a, b, c, d, a]
    On utilise des ensembles
    [a, b, c, d]
    ne suffit pas, je voudrais obtenir un ensemble [b,c,d]

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Je ferais plutot comme ceci:

    une Map<Timestamp,Donnee> contenu
    un Set<Timestamp> (doublons)
    et l'algo suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    pour chaque entree lue
      if map.contains(timestamp)
         doublons.add(timestamp)
      sinon
        contenu.add(timestamp,donnee)
    fin pour
    four chaque doublon
       contenu.remove(doublon)

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Par défaut
    Bon, j'ai continué sur une idée que j'ai eu, et j'obtiens un résultat
    à peu près (en fait tout à fait) cohérent:
    En gros, j'ai modifié un peu mon bean de donnée comme suit:
    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
    package Main;
     
    import java.sql.Timestamp;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    public class bean {
     
        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        private Timestamp date;
        private Float mesure;
        private boolean aDoublon = false;
     
        bean(String date, float valeur) {
            try {
                this.date = new Timestamp(sdf.parse(date).getTime());
                this.mesure = valeur;
            } catch (ParseException ex) {
                Logger.getLogger(bean.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
     
        public Timestamp getDate() {
            return date;
        }
     
        public Float getMesure() {
            return mesure;
        }
     
        public boolean aDoublon() {
            return aDoublon;
        }
     
        @Override
        public boolean equals(Object o) {
            if (o == this) {
                aDoublon = true;
                return true;
            }
            if (!(o instanceof bean)) {
                return false;
            }
            final bean unAutreBean = (bean) o;
            if (unAutreBean.getDate().equals(this.getDate())) {
                this.aDoublon = true;
                unAutreBean.aDoublon = true;
                return true;
            } else {
                return false;
            }
        }
     
        @Override
        public int hashCode() {
            int hash = 7;
            hash = 47 * hash + (this.sdf != null ? this.sdf.hashCode() : 0);
            hash = 47 * hash + (this.date != null ? this.date.hashCode() : 0);
            hash = 47 * hash + (this.mesure != null ? this.mesure.hashCode() : 0);
            hash = 47 * hash + (this.aDoublon ? 1 : 0);
            return hash;
        }
     
        public void afficher() {
            StringBuilder tmp = new StringBuilder();
            tmp.append(sdf.format(this.date));
            tmp.append("\t");
            tmp.append(this.mesure);
            tmp.append("\t");
            tmp.append(this.aDoublon);
            System.out.println(tmp.toString());
        }
    }
    Donc avec en gros un tag aDoublon et une redéfinition de la méthode
    equals (normal) avec dans cette dernière une facon de qualifier la donnée
    testée avec une autre...

    Le "main":
    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
    package Main;
     
    import java.text.ParseException;
    import java.util.ArrayList;
    import java.util.Iterator;
     
    public class testArrayList {
     
        private ArrayList<bean> listBeanClassique = new ArrayList<bean>();
        private ArrayList<bean> listBeanEvolue = new ArrayList<bean>();
     
        public void testArrayList() throws ParseException {
            //////////////////////////////////////////////////
            // les data
            // bean1 = bean2
            // bean5 = bean6
            bean unBean1 = new bean("2012-01-01 00:00:00", 0F);
            bean unBean2 = new bean("2012-01-01 00:00:00", 1F);
            bean unBean3 = new bean("2012-01-01 00:00:02", 2F);
            bean unBean4 = new bean("2012-01-01 00:00:03", 3F);
            bean unBean5 = new bean("2012-01-01 00:00:04", 4F);
            bean unBean6 = new bean("2012-01-01 00:00:04", 5F);
     
            //////////////////////////////////////////////////
            // Classique
            listBeanClassique.add(unBean1);
            listBeanClassique.add(unBean2);
            listBeanClassique.add(unBean3);
            listBeanClassique.add(unBean4);
            listBeanClassique.add(unBean5);
            listBeanClassique.add(unBean6);
     
     
            //////////////////////////////////////////////////
            // Evolué entre de grosses guillemets!!!
            // aucune prétention de ma part ;-)
            if (!listBeanEvolue.contains(unBean1)) {
                listBeanEvolue.add(unBean1);
            }
            if (!listBeanEvolue.contains(unBean2)) {
                listBeanEvolue.add(unBean2);
            }
            if (!listBeanEvolue.contains(unBean3)) {
                listBeanEvolue.add(unBean3);
            }
            if (!listBeanEvolue.contains(unBean4)) {
                listBeanEvolue.add(unBean4);
            }
            if (!listBeanEvolue.contains(unBean5)) {
                listBeanEvolue.add(unBean5);
            }
            if (!listBeanEvolue.contains(unBean6)) {
                listBeanEvolue.add(unBean6);
            }
            // plus un petit traitement
            Iterator iterator = listBeanEvolue.iterator();
            while (iterator.hasNext()) {
                bean a = (bean) iterator.next();
                if (a.aDoublon()) {
                    iterator.remove();
                }
            }
     
     
            //////////////////////////////////////////////////
            // Affichage
            System.out.println("Classique");
            for (bean a : listBeanClassique) {
                a.afficher();
            }
     
            System.out.println("Sans doublons");
            for (bean a : listBeanEvolue) {
                a.afficher();
            }
     
        }
    }

    Le résultat:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Classique
    2012-01-01 00:00:00	0.0	true
    2012-01-01 00:00:00	1.0	true
    2012-01-01 00:00:02	2.0	false
    2012-01-01 00:00:03	3.0	false
    2012-01-01 00:00:04	4.0	true
    2012-01-01 00:00:04	5.0	true
    Sans doublons
    2012-01-01 00:00:02	2.0	false
    2012-01-01 00:00:03	3.0	false


    Je vais tester çà sur un set de données conséquent, environ 10Mo de texte,
    mais j'ai bien peur que les performances ne soient pas au rendez vous, donc
    le sujet est toujours ouvert, et si quelqu'un a une meilleure solution, je suis
    vraiment preneur!

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Par défaut
    Bon, j'ai modifié mon code, j'ai lancé ma lecture du fichier, je suis allé
    fumer une clope, je suis revenu, j'ai checké mes mails, j'ai vu ton message
    tchize_ , et c'est encore en train de faire son job
    Bref, c'est vraiment pas acceptable en terme de performance lol

    @tchize_:
    Je pense avoir adopté dans mon dernier test ton algo, mais il faut se
    rendre à l'évidence, ca marche pour quelques (petits) milliers de lignes
    parsées, mais dans mon cas, je crois que c'est mort...
    j'utilise un ArrayList parce que:
    1- je peux le dimensionner presque exactement
    2- parce que les ArrayList sont plus performants dans les ajouts en fin de liste, ce qui correspond bien à mon cas, car les lignes de mon fichier ne sont pas forcement dans un ordre chronologique
    3- parce que un Collection.sort() est vraiment très rapide
    du coup la solution que tu évoques et que je viens de tester n'est pas satisfaisante. Je pensais à la base faire un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    lecture ligne à ligne:
         je parse et ajoute ma ligne
    classement de la liste en ordre chronologie (vu que ma contrainte est sur la date)
    lecture de ma liste par ligne
         si ma ligne != ligne suivante
         ajout dans une nouvelle liste
    ...
    bref, ce n'est pas réellement satisfaisant, quelque soit la méthode...
    un peu déprimé ce soir

  6. #6
    Modérateur

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

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Tu veux dire

    - que tu as essayé d'adapter le code de tchize en remplaçant les Map et Set par des List, et que tu trouves ça (sans surprise) très inefficace, ou

    - que tu as pris son algo tel que, et que ce n'est pas assez rapide, alors tu as essayé avec des List à la place (ce qui ne risque pas de faire mieux)

    ?

    Edit : je viens de tenter l'algo de tchize_ sur des données aléatoires dans un fichier de 10Mo+. Le dédoublonnage avec classement des résultats prend environ 4 secondes sur ma machine, l'écriture des résultats 1 seconde. Soit un traitement total d'à peu près 5 secondes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Février 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 41
    Par défaut
    t'as raison, je vais revoir ma copie, je ne sais plus trop ce que
    j'essaye de faire...
    Je vais reprendre en l'état l'algo de tchize, remplacer mes lists
    par des maps et sets, et je vous tiens au courant

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

Discussions similaires

  1. [ArrayList] Enlever les doublons
    Par GLDavid dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 13/05/2012, 02h43
  2. Enregistrement courant après refresh [cas particulier]
    Par say dans le forum Bases de données
    Réponses: 8
    Dernier message: 02/08/2005, 15h59
  3. Réponses: 2
    Dernier message: 05/01/2004, 11h23

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