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 meilleur algo parcours + ConcurrentModificationException


Sujet :

Collection et Stream Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 32
    Par défaut ArrayList meilleur algo parcours + ConcurrentModificationException
    Bonjour ,

    Je cherche a optimiser mon programme qui sert a configurer de maniere automatique des parametres stockes dans des fichiers INI . L´affichage des parametres se fait dans un tree .

    Mes parametres sont regroupes dans des " modules " . Chaque module contient un ArrayList (nomme lConfigurationItem) de "ConfigurationItem" .Lorsque je veux ecrire dans ces parametres je dois parcourir un a un cette Arraylist pour appeler la methode apply() pour chacun d´entre eux :

    Code JAVA :
    for(ConfigurationItem ci: lConfigurationItem)
    if(ci.isActive()) ci.apply();

    Comme vous pouvez voir , J´utilise une boucle for toute simple . J´ai fait une recherche et j´ai ete surpris de voir que dans les exemples ; ils utilisaient en general un iterator couples a des next() . Est ce que cette methode est plus efficace en terme de performance pour parcourir l´ArrayList ?

    Lors de ce parcours , pour certains parametres ; la methode apply() provoque un ajout de parametres dans le module et l´ArrayList ce qui provoque un ConcurrentModificationException . Suis je oblige de passer par la methode : List list = Collections.synchronizedList(new ArrayList(...));
    ? Vector c´est synchronise mais depreciee ...

    Sinon dans l´APi de ArrayList :
    http://java.sun.com/j2se/1.5.0/docs/api/
    Il est ecrit qu´utiliser la methode ensureCapacity ameliore les performances . Au maximum le nombre de parametres atteint 30. Ce qui ne fait que 20 cases supplementaires dans l´ArrayList initial . Je ne pense pas que cela soit significatif !! De votre experience, connaissez vous d´autres methodes pour ameliorer significativement les performances avec l´ArrayList ?

    Merci beaucoup et bonne journee

  2. #2
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 32
    Par défaut
    Apperemment , il y a 4 possibilitees pour parcourir un ArrayList() :

    foreach loop :

    ArrayList<String> a = new ArrayList<String>();
    . . .
    for (String s : a) {
    System.out.println(s);
    }

    for loop avec index :

    for (int i = 0; i < a.size(); i++) {
    System.out.println(a.get(i));
    }

    Iterator<E>

    for (Iterator<String> iter = a.iterator(); iter.hasNext(); ) {
    System.out.println(iter.next());
    }

    ListIterator<E>

    Mais apres la meilleure en terme de performance , je n´en suis pas sur

  3. #3
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par gerudo Voir le message
    for(ConfigurationItem ci: lConfigurationItem)
    if(ci.isActive()) ci.apply();

    Comme vous pouvez voir , J´utilise une boucle for toute simple . J´ai fait une recherche et j´ai ete surpris de voir que dans les exemples ; ils utilisaient en general un iterator couples a des next() . Est ce que cette methode est plus efficace en terme de performance pour parcourir l´ArrayList ?
    C'est strictement la même chose : la boucle for étendus (que tu utilises) est apparut depuis Java 5 seulement, et utilise en fait l'Iterator de manière plus simple



    Citation Envoyé par gerudo Voir le message
    Lors de ce parcours , pour certains parametres ; la methode apply() provoque un ajout de parametres dans le module et l´ArrayList ce qui provoque un ConcurrentModificationException . Suis je oblige de passer par la methode : List list = Collections.synchronizedList(new ArrayList(...));
    ? Vector c´est synchronise mais depreciee ...
    Si tu manipules tes listes depuis différents threads tu sera obligé de passer par de la synchronisation.

    Mais d'après ta description la ConcurrentModificationException ne vient pas de là : lorsqu'on modifie directement une liste pendant son parcours (via Iterator ou for étendus donc), on ne doit pas la modifier (ajout/suppression d'élément) sous peine de "casser" le parcourt de l'itérateur...

    Pour éviter cela il faut passer par l'Iterator (pour la suppression) ou un ListIterator (pour l'ajout).



    Citation Envoyé par gerudo Voir le message
    Sinon dans l´APi de ArrayList :
    http://java.sun.com/j2se/1.5.0/docs/api/
    Il est ecrit qu´utiliser la methode ensureCapacity ameliore les performances . Au maximum le nombre de parametres atteint 30. Ce qui ne fait que 20 cases supplementaires dans l´ArrayList initial . Je ne pense pas que cela soit significatif !!
    Sur de si petite quantité cela n'aura qu'un impact minime (tu auras au pire un ou deux allocations en moins).

    Par contre si tes ArrayList arrive à une taille fixe, il peut être intéressant d'utiliser trimToSize() pour éviter de "gaspiller" de la mémoire...


    Citation Envoyé par gerudo Voir le message
    De votre experience, connaissez vous d´autres methodes pour ameliorer significativement les performances avec l´ArrayList ?
    Tu as vraiment des problèmes de performances ??? Si oui recherche l'origine exact plutôt que de vouloir optimiser à tout prix (cette dernière approche n'est généralement pas très judicieuse).

    Une optimisation qui peut être fait sur les liste en "RandomAccess" c'est d'utiliser l'accès par index pour le parcours :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    	if (list instanceof RandomAccess) {
    		final int size = list.size();
    		for (int i=0; i<size; i++) {
    			Object current = list.get(i);
    			// ...
    		}
    	}
    C'est normalement plus performant (quoique sur de si petite quantité la différence ne dois pas être flagrante du tout), mais pas exempt de défaut :
    • C'est nettement moins lisible
    • Les modifications de la liste pendant le parcours peuvent entrainer des états incohérents qui ne seront pas détecté par une ConcurrentModifException, mais qui pourront entrainer d'autres problèmes...



    a++

    [EDIT] Tu as posté entre temps...
    Pour le parcours je te conseille le for-each (ou for étendus) autant que possible : c'est le plus lisible.
    Ensuite viennent l'Iterator ou le ListIterator si tu as besoin d'utiliser leurs méthodes spécifique.
    Perso je te déconseillerais l'accès par index, car s'il est potentiellement le plus rapide sur une ArrayList, il peut se révéler catastrophique sur tout autre type de liste...

  4. #4
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 32
    Par défaut
    Merci beaucoup,

    Je vais suivre tes conseils et je mettrai mon post en resolu demain si tout se deroule bien .
    Mon probleme de performances , ca vient que j´utilisais la librairie INI4J auparavant pour les modificatiosn dans les ficheirs INI et c´etait horriblement lent .
    Les performances sont largement meilleures en utilisant mes propres algos, c´est bizarre.

    Merci et bonne journee

  5. #5
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 32
    Par défaut
    Bonjour,

    Je ne parviens pas a lever l´exception en utilisant un ListIterator ou un Iterator .
    Voici mon code :

    public void apply() {

    ListIterator it = lConfigurationItem.listIterator();

    while (it.hasNext()){

    ConfigurationItem ci = (ConfigurationItem) it.next();
    ci.apply();

    for (ConfigurationItem ccc: lConfigurationItemAdded){
    it.add(ccc);
    }
    }

    }

    lConfigurationItem est la liste des parametres contenues dans le dossier /classe (Module) du tree ou je me trouve .
    lConfigurationItemAdded est la liste des parametres ajoutes dans l´arbre apres avoir appele la methode apply()
    ci est un parametre , il se trouve dans une classe "Configuration Item " ou est presente la methode apply(). La methode apply permet de changer la configuration des parametres .
    Le probleme c´est qu´avec cette methode cela peut changer dynamiquement le nombre de parametres dans le module en enlevant et en en supprimant . D´ou une exception : ConcurrentModificationException


    J´utilise le debuggeur pour suivre la procedure mais des qu´il arrive a :
    it.add(ccc); L´exception est lancee

    Je commence a desesperee et me dire que c´est d´un niveau un peu trop elevee ce que je fais

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

Discussions similaires

  1. [Exercice] Le meilleur algo (sous Excel)
    Par argyronet dans le forum Défis
    Réponses: 10
    Dernier message: 29/09/2015, 08h22
  2. Meilleur algo de détection d'objet
    Par Colloc dans le forum Traitement d'images
    Réponses: 20
    Dernier message: 07/02/2012, 22h27
  3. Réponses: 0
    Dernier message: 30/04/2009, 10h32
  4. quel est le meilleur algo de tri de liste ?
    Par sony351 dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 24/07/2005, 02h00

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