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 :

Q: Remplir une ArrayList ligne par ligne tout en triant


Sujet :

Collection et Stream Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut Q: Remplir une ArrayList ligne par ligne tout en triant
    Chers Javaïstes, bonjour.
    Une question à réponse courte, je pense, mais à explication longue ...

    Lors de l'emploi d'ArrayList's, il est souvent recommendé d'utiliser un Iterator ou un ListIterator, car plus performant pour les longues listes (la mienne : 35.100 lignes) qu'un for ou un while().

    Un besoin courant est, il me semble, de devoir remplir une ArrayList ligne par ligne par ordre croissant d'une valeur de référence, c à d en positionnant chaque nouvelle soit entre deux lignes existant dans la liste, soit en fin de liste, soit même en modifiant une ligne dont la valeur de référence est la même que celle de la ligne à insérer.
    Mais lorsqu'un Iterator ou un ListIterator est employé et que la logique détecte que la dernière ligne lue de l'ArrayList (à l'aide de hasNext()), pour en comparer la valeur de référence à celle de l'élément à insérer, est la première dont la valeur de référence est supérieure à la valeur de référence de l'élément à insérer, et qu'il faut donc reculer d'un élément dans l'ArrayList, quelle instruction d'itérateur est propice pour insérer l'élément juste avant la ligne où en est arrivée le hasNext() ? hasPrevious() ?

    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
            Object valeurPuiss;
            ListIterator<DonnéesHor> lItérat;
            boolean laValeurATrouvéSaPlace;
            
            for (int noLigne_TablePrinc = lignesDébutFinDonnées[0] ;
                     noLigne_TablePrinc <= lignesDébutFinDonnées[1] ;
                     noLigne_TablePrinc++ )
            {               
                valeurPuiss = tablePrinc.getValueAt(noLigne_TablePrinc, puissTable);
                if (valeurPuiss != null && (Class<?>) valeurPuiss.getClass() == BigDecimal.class    )
                {   
                    lItérat = donnéesHor_HPlHCr[1].listIterator();
                    laValeurATrouvéSaPlace = false;
    
                    /* Trouver entre quelles lignes de la liste 'listeFréquConsoPuiss' insérer
                     * ou bien à quelle ligne ajouter cette valeur de puissance.       */
                    while(lItérat.hasNext())
                    {   
                        DonnéesHor échantDonnéesHor = lItérat.next();
                        
                        // Si 'puissAnnoncée' de 'échantDonnéesHor' est < 'valeurPuiss', passer au suivant.
                        if ((échantDonnéesHor.puissAnnoncée).compareTo((BigDecimal) valeurPuiss) == -1)
                        {   // Rien à faire.
                        } else
    
                        // Si 'puissAnnoncée' de 'échantDonnéesHor' est = 'valeurPuiss', modifier ce dernier.
                        if ((échantDonnéesHor.puissAnnoncée).compareTo((BigDecimal) valeurPuiss) == 0)
                        {   
                            // listeFréquConsoPuiss_HCr().donnéesHor_HCr.puissAnnoncée;
                            // 'puissAnnoncée' reste de même valeur.
                            échantDonnéesHor.nbreApparitions++;
                            // Remplace le dernier élément renvoyé par next()
                            lItérat.set(échantDonnéesHor);
                            laValeurATrouvéSaPlace = true;
                        } else
    
                        /* Si 'puissAnnoncée' de 'échantDonnéesHor' > 'valeurPuiss', insérer 
                         * entre cette ligne et la précédente --> RECULER D'UNE LIGNE.      */
                        if ((échantDonnéesHor.puissAnnoncée).compareTo((BigDecimal) valeurPuiss) == +1)
                        {
                            lItérat.hasPrevious();
                            DonnéesHor donnéesHor_HCr = new DonnéesHor();
                            donnéesHor_HCr.puissAnnoncée = ((BigDecimal) valeurPuiss);
                            donnéesHor_HCr.nbreApparitions = 1;
                            donnéesHor_HPlHCr[1].add(? ? ? , donnéesHor_HCr);
                            laValeurATrouvéSaPlace = true;
                        }   // Fin des 3 'if (((BigDecimal) valeurPuiss).compareTo(
                    }   // Fin du 'while(itérat.hasNext())
                        // Si fin de la liste, ajouter un nouveau 'donnéesHor' en fin de liste.
                    if (laValeurATrouvéSaPlace != true)
                    {
                        DonnéesHor donnéesHor_HCr = new DonnéesHor();
                        donnéesHor_HCr.puissAnnoncée = ((BigDecimal) valeurPuiss);
                        donnéesHor_HCr.nbreApparitions = 1;
                        donnéesHor_HPlHCr[HCREUSES_IDX].add(donnéesHor_HCr);
                        // listeFréquConsoPuiss_HCr.get(listeFréquConsoPuiss_HCr.size()-1).nbreApparitions = 22;
                    }
                }   // Fin du 'if (valeurPuiss
            }   // Fin du 'for (noLigne_TablePrinc
            return listes_PuissEnerg;
    Problème d'intérêt général, n'est-ce pas ?
    Merci d'avance.
    "Ah oui ! Juste encore cette toute dernière petite question ..." (Columbo - Peter Falk)

  2. #2
    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 Chavadam Voir le message
    Lors de l'emploi d'ArrayList's, il est souvent recommendé d'utiliser un Iterator ou un ListIterator, car plus performant pour les longues listes (la mienne : 35.100 lignes) qu'un for ou un while().
    Pas du tout. C'est le cas pour les List en général, quand on ne sait pas si c'est une ArrayList ou une LinkedList ou quoi, et qu'on ne sait donc pas si on peut accéder aux éléments rapidement juste avec leurs indices. Comme on ne sait pas si on peut, il ne faut pas le faire, et donc préférer les parcours à base d'Iterator qui, eux, s'adaptent bien à toutes les List.

    Mais quand on sait qu'on est vraiment sur une ArrayList, on peut accéder aux éléments directement grâce à leurs indices, comme dans un array, c'est pour ça que la classe s'appelle comme ça.

    Toujours comme avec un array, C'est, par contre, une classe pour laquelle il est très cher d'ajouter ou enlever des éléments ailleurs qu'à la fin. Parce que ça oblige à tout décaler pour faire de la place ou enlever le vide.

    Citation Envoyé par Chavadam Voir le message
    Un besoin courant est, il me semble, de devoir remplir une ArrayList ligne par ligne par ordre croissant d'une valeur de référence, c à d en positionnant chaque nouvelle soit entre deux lignes existant dans la liste, soit en fin de liste, soit même en modifiant une ligne dont la valeur de référence est la même que celle de la ligne à insérer.
    Pas très courant, non. Si l'ordre des éléments dépend de leurs valeurs, on utilisera plutôt un SortedSet ou un SortedMap. Ils sont là pour ça, et permettent notamment une recherche dichotomique de l'endroit où ranger un nouvel élément.

    Autre utilisation courante : entasser les éléments dans une List à la queue leu-leu sans s'occuper de leur ordre, puis ne trier la List qu'à la fin, quand tous les éléments sont là. Bien plus efficace.

    Citation Envoyé par Chavadam Voir le message
    Mais lorsqu'un Iterator ou un ListIterator est employé et que la logique détecte que la dernière ligne lue de l'ArrayList (à l'aide de hasNext()), pour en comparer la valeur de référence à celle de l'élément à insérer, est la première dont la valeur de référence est supérieure à la valeur de référence de l'élément à insérer, et qu'il faut donc reculer d'un élément dans l'ArrayList, quelle instruction d'itérateur est propice pour insérer l'élément juste avant la ligne où en est arrivée le hasNext() ? hasPrevious() ?
    Non, previous(). Comme son nom l'indique ça fonctionne comme next() mais dans l'autre sens.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Chavadam Voir le message
    Lors de l'emploi d'ArrayList's, il est souvent recommendé d'utiliser un Iterator ou un ListIterator, car plus performant pour les longues listes (la mienne : 35.100 lignes) qu'un for ou un while().
    Non, c'est juste recommendé pour deux choses:
    Quand tu ne connais pas l'implémentation
    Parce que ça détecte les modification concurrentes et permet de voir ce genre d'erreur

    Citation Envoyé par Chavadam Voir le message
    , quelle instruction d'itérateur est propice pour insérer l'élément juste avant la ligne où en est arrivée le hasNext() ? hasPrevious()
    Aucune, Iterator permet juste de supprimer, ListIterator permet de remplace. Aucun ne permet d'insertion.

    Si tu dois travailler avec un List et que tu dois faire des insertion / suppression en grand nombre à différents endroit, La LinkedList est à préférer car une insertion se fait en O(1)

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par tchize_ Voir le message
    Aucune, Iterator permet juste de supprimer, ListIterator permet de remplace. Aucun ne permet d'insertion.
    ListIterator permet bien l'insertion de valeur, via sa méthode add()...




    Par contre comme thelvin, je pense qu'il serait plutôt préférable de se contenter de la trier à la fin du traitement...


    a++

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

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    pas vu.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Chers Thelvin, AdiGuba, Tchize,
    Merci beaucoup pour vos réponses ... bien expliquées.

    J'ai compris que dans mon cas d'application, il eut mieux valu
    - utiliser une boucle 'for()' ou 'while()' avec une variable noLigneListe plutôt qu'un itérateur,
    - utiliser une LinkedList, un SortedSet ou un SortedMap
    - appliquer une méthode de tri sur base de la valeur seulement après avoir avoir rempli dans mon ArrayList les ± 35.100 valeurs par ordre de leur disponibilité.

    Pour l'instant, j'essaye de terminer ma tentative de solution apparemment presque complète et basée sur un itérateur, telle que j'en ai passé le code dans mon exposé initial.
    OK Thelvin pour le listItérat.previous();.

    Ce qui ne va pas encore : Parfois, un élément doit être inséré avant l'élément qui est en première place dans l'ArrayList, pour que cet élément à insérer prenne lui la toute première place. Quelle instruction utiliser ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    donnéesHor_HPlHCr[1].add(-1 , donnéesHor_HCr);
    ne fonctionne pas.
    Inutile aussi d'essayer listItérat.previous(); lorsque l'itérateur est sur le premier élément, car il n'y a pas de "previous" dans ce cas. Pratiquement, l'élément à insérer se place après le premier élément, ce qui constitue une erreur.
    J'imagine qu'avec itérateur ou avec boucle 'for()' et noLigneListe, il faudra dans les deux cas copier tous les éléments de l'ArrayList une case plus loin et placer le nouvel élément noLigneListe 0 comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            listItérat = donnéesHor_HPlHCr[1].listIterator();
            listItérat.set(échantDonnéesHor);
    Je me trompe ?

    Merci d'avance.
    "Ah oui ! Juste encore cette toute dernière petite question ..." (Columbo - Peter Falk)

  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
    Copier les éléments les uns après les autres, c'est le boulot de la liste, pas le tien. Toi tu lui dis que tu veux insérer un truc, et elle, elle le fait. Je confirme, par contre, qu'une ArrayList va bel et bien devoir se taper le boulot de déplacer tous les éléments, et que c'est une opération chère.
    Vu que tu veux l'insérer au début, ça veut dire que tu veux l'insérer à l'index 0 et que tout le reste incrémente son index. Si tu voulais insérer à l'index 27, tu ferais add(27, element). Donc pour insérer à l'index 0, tu fais add(0, element). C'est juste la même chose.

    Et si tu voulais utiliser un itérateur, il suffit de revenir au début jusqu'à ce que hasPrevious() renvoie false. Une fois que tu es à cet endroit, l'itérateur se comporte exactement comme d'habitude, et si tu lui demandes d'insérer un élément, il l'insérera à l'index qu'il aurait donné en faisant nextIndex(). C'est-à-dire, en début de liste, 0.

    Il n'y a juste rien d'original, particulier, ou spécial dans le fait d'ajouter en début de liste. Ça fonctionne exactement comme ajouter ailleurs qu'en début de liste.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2011
    Messages : 17
    Points : 13
    Points
    13
    Par défaut
    Dans ton cas je pense qu'il vaut mieux ajouter tout, puis faire une Collections.sort(maListe)
    Le tri sera beaucoup plus efficace que si tu le faisait à chaque ajout.

    Si tu ne peux pas avoir toutes tes valeurs avant de proceder au tri... alors tu t'es trompé d'implémentation pour ta liste et il vaut mieux utiliser LinkedList plutot que ArrayList.

    petit article de la FAQ à propos de ça : http://java.developpez.com/faq/java/...IONS_info_list

    Bon courage =)

  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
    Citation Envoyé par VincentCh Voir le message
    Si tu ne peux pas avoir toutes tes valeurs avant de proceder au tri... alors tu t'es trompé d'implémentation pour ta liste et il vaut mieux utiliser LinkedList plutot que ArrayList.
    Non... Pas une liste, un TreeSet. Ajouter un élément à la bonne place devrait être fait par recherche dichotomique, pas du début à la fin.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    263
    Détails du profil
    Informations personnelles :
    Âge : 73
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2008
    Messages : 263
    Points : 121
    Points
    121
    Par défaut
    Bonjour à tous.
    Et merci bcp à Thelvin, Tchize, adiGuba, et VincentCh.

    Vos réponses m'ont été vraiment utiles pour m'orienter ma solution qui fonctionne apparemment bien : For( ; ; ) plutôt que Iterator. Pas de temps d'attente gênant malgré une liste de départ de 35.100 lignes. Placement au bon endroit dans la liste dès la lecture de la liste de départ. Vos remarques me portent à (re)voir pas mal de notions (LinkedList, ...), et comme Java est l'un de mes hobbies, je prends le temps de le faire, mais pas toujours directement.

    Merci encore.
    "Ah oui ! Juste encore cette toute dernière petite question ..." (Columbo - Peter Falk)

  11. #11
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Chavadam Voir le message
    Vos réponses m'ont été vraiment utiles pour m'orienter ma solution qui fonctionne apparemment bien : For( ; ; ) plutôt que Iterator.
    Heu...
    Perso je conseillerais plutôt le for-each ou l'Iterator à l'utilisation d'un for par index.

    Le for par index est trop dépendant de l'implémentation de la collection.
    C'est peut-être plus performant sur une ArrayList, le gain ne doit pas être énorme.
    Par contre cela peut s'avérer catastrophique avec certaines implémentation (comme LinkedList par exemple).



    L'Iterator (et donc le for-each) garantie le meilleur compromis...




    a++

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

Discussions similaires

  1. lire une base de donnee ligne par ligne
    Par thildouille dans le forum Langage
    Réponses: 9
    Dernier message: 03/06/2011, 00h50
  2. Réponses: 8
    Dernier message: 18/07/2010, 21h16
  3. Réponses: 12
    Dernier message: 14/05/2008, 17h15
  4. Réponses: 3
    Dernier message: 16/10/2007, 20h45
  5. [WD10] remplir une table ligne par ligne
    Par clades dans le forum WinDev
    Réponses: 1
    Dernier message: 05/07/2007, 20h59

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