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

avec Java Discussion :

Problème de type : java.util.ConcurrentModificationException lors de la suppression


Sujet :

avec Java

  1. #1
    Membre du Club Avatar de mobi_bil
    Profil pro
    Inscrit en
    Février 2009
    Messages
    242
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 242
    Points : 52
    Points
    52
    Par défaut Problème de type : java.util.ConcurrentModificationException lors de la suppression
    Bonjour à tous,
    Voici le programme suivant :

    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
     
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
     
     
    public class app {
     
    public static void main(String[] args) {
     
    List<double[]> liste=new ArrayList();
    LinkedList<List<double[]>> double_liste=new LinkedList<List<double[]>>();
     
     
       for (int j=0;j<4;j++)	 
    	 {
                      for (int i=j;i<j+4;i++)
        	          liste.add(new double[] {i});
     
                       double_liste.add(liste);
     
    	  }
     
    	  for (List<double[]> ls:double_liste)
    		   double_liste.remove(double_liste.indexOf(ls));
     
     
     
     
    	}
     
    }
    Mon but est de supprimer de chaque liste l'élément qui a pour valeur 3, en testant ce programme, je trouve les erreurs suivantes :

    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)
    at app.main(
    app.java:29)

    Je sais que l'erreur est au niveau de l'instruction
    double_liste.remove(double_liste.indexOf(ls));
    mais je n'arrive pas à trouver la solution. Merci pour votre aide.

  2. #2
    Membre expérimenté
    Avatar de visiwi
    Profil pro
    Inscrit en
    Février 2008
    Messages
    1 050
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 1 050
    Points : 1 340
    Points
    1 340
    Par défaut
    Salut,

    Tu parcours une liste (avec ta boucle étendue c'est comme si tu faisait une itération) et en même temps tu modifie ta liste. Cela engendre invariablement une exception de ce type.

    Un palliatif est de parcourir la liste à l'envers :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (int i = double_liste.size() - 1 ; i >= 0 ; i--) {
    	double_liste.remove(double_liste.get(i));
    }
    Le tableau de double semble inutile puisque tu n'a qu'une seule valeur dedans.

    Ne serait-ce pas plutot que chose comme ça ?
    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
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
     
    public class T {
     
    	public static void main(String[] args) {
    		List<Double> liste = new ArrayList<Double>();
    		LinkedList<List<Double>> double_liste = new LinkedList<List<Double>>();
     
    		for (int j = 0; j < 4; j++) {
    			for (double i = j; i < j + 4; i++) {
    				liste.add(i);
    			}
    			double_liste.add(liste);
    		}
     
    		for (int i = double_liste.size() - 1 ; i >= 0 ; i--) {
    			List<Double> dList = double_liste.get(i);
    			for (int j = dList.size() - 1 ; j >= 0 ; j--) {
    				if (dList.get(j) == 3) {
    					dList.remove(j);
    				}
    			}			
    		}
    	}
     
    }

  3. #3
    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 visiwi Voir le message
    Tu parcours une liste (avec ta boucle étendue c'est comme si tu faisait une itération) et en même temps tu modifie ta liste. Cela engendre invariablement une exception de ce type.
    En effet : lors d'un parcours via Iterator, la collection ne doit pas être modifié sous peine de problème plus ou moins simple selon les cas et l'implémentation...

    Pour éviter ce genre de désagrément, les Iterators sont "fail-fast", c'est à dire qu'il planteront via une ConcurrentModificationException dès qu'ils détectent la moindre modification externe...

    Citation Envoyé par visiwi Voir le message
    Un palliatif est de parcourir la liste à l'envers :
    Surtout pas !

    Cela peut marcher dans ce cas précis... mais tu risques de retrouver des problèmes si tu ajoutes des éléments dans la liste. De plus sauf cas bien spécifique l'accès direct via index est à déconseiller au profit des Iterators.

    Avec une LinkedList de taille assez conséquente cela peut même s'avérer désastreux en terme de performance !


    En fait il faut utiliser l'Iterator "manuellement", afin de pouvoir utiliser sa méthode remove() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Iterator<List<double[]>> iterator = double_liste.iterator();
    while (iterator.hasNext()) {
    	List<double[]> ls = iterator.next(); // On récupère l'élément courant
     
    	iterator.remove(); // On supprime l'élément courant
    }
    A noter enfin qu'on peut utiliser une ListIterator qui propose des fonctions plus spécifique aux listes...


    a++

  4. #4
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    On peut aussi supprimer les éléments d'une liste parcourue avec un itérateur, mais uniquement avec la méthode remove() de l'itérateur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Iterator iter = maListe.iterator();
    while(iterator.hasNext()) {
       iter.next();
       iter.remove();
    }
    EDIT : grillé pour iterator.remove()
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  5. #5
    Membre du Club Avatar de mobi_bil
    Profil pro
    Inscrit en
    Février 2009
    Messages
    242
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 242
    Points : 52
    Points
    52
    Par défaut
    Bonjour à tous, et merci pour votre aide.

    Envoyé par adiGuba
    En fait il faut utiliser l'Iterator "manuellement", afin de pouvoir utiliser sa méthode remove() :

    Iterator<List<double[]>> iterator = double_liste.iterator();
    while (iterator.hasNext()) {
    List<double[]> ls = iterator.next(); // On récupère l'élément courant

    iterator.remove(); // On supprime l'élément courant
    }
    J'ai modifie le programme en utilisant ce bloc, mais j'ai eu un autre type d'erreur :

    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
     
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Iterator;
     
    public class app {
     
     
     
     
     
     
    public static void main(String[] args) {
     
     List<Double> liste=new ArrayList();
     LinkedList<List<Double>> double_liste=new LinkedList<List<Double>>();
     
     
    	  for (double j=0;j<4;j++)	 
    	  {
             for (double i=0;i<4;i++)
        	      liste.add(i);
     
                  double_liste.add(liste);                      
     
    	  }
     
    	  Iterator<List<Double>> iterator=double_liste.iterator();
    	       while (iterator.hasNext())
    	       {
    	    	   List<Double> ls=iterator.next();
    	    	   for (double i:ls)
    	    		    if (i==0) iterator.remove();
     
    	       }
     
    	}
     
    }
    Exception in thread "main" java.lang.IllegalStateException
    at java.util.LinkedList$ListItr.remove(Unknown Source)
    at app.main(
    app.java:33)

    Si quelqu'un peut me le corriger, merci.

  6. #6
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Comme tu boucles sur ta liste ls, si elle contient deux fois la valeur "0", tu invoques deux fois la commande "iterator.remove()".

    Or, la deuxième fois, tu lèves l'exception car tu ne peux supprimer l'élément qui n'est plus dans la liste.

    Tu dois donc sortir de ton for dès que la condition est remplie (avec un "break" par exemple).
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  7. #7
    Membre du Club Avatar de mobi_bil
    Profil pro
    Inscrit en
    Février 2009
    Messages
    242
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 242
    Points : 52
    Points
    52
    Par défaut
    Citation Envoyé par CyberChouan Voir le message
    Comme tu boucles sur ta liste ls, si elle contient deux fois la valeur "0", tu invoques deux fois la commande "iterator.remove()".

    Or, la deuxième fois, tu lèves l'exception car tu ne peux supprimer l'élément qui n'est plus dans la liste.
    Ou est le problème si je veux supprimer deux éléments qui ont la même valeur ?

  8. #8
    Rédacteur
    Avatar de CyberChouan
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Janvier 2007
    Messages : 2 752
    Points : 4 314
    Points
    4 314
    Par défaut
    Avec ton code tu ne supprimes pas deux éléments qui ont la même valeur, mais deux fois le même élément (à savoir, c'est la liste ls toute entière qui est supprimée de la liste liste_double)
    Avant de poster, pensez à regarder la FAQ, les tutoriaux, la Javadoc (de la JRE que vous utilisez) et à faire une recherche
    Je ne réponds pas aux questions techniques par MP: les forums sont faits pour ça
    Mes articles et tutoriaux & Mon blog informatique

  9. #9
    Membre du Club Avatar de mobi_bil
    Profil pro
    Inscrit en
    Février 2009
    Messages
    242
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 242
    Points : 52
    Points
    52
    Par défaut
    Dans ce cas, comment faire pour supprimer un élément de la liste qui est elle-même inclue dans une double_liste ? mERCI pOUR vOTRE aIDE .

  10. #10
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    570
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 570
    Points : 340
    Points
    340
    Par défaut
    Ici tu supprimes non pas l'élément de la sous liste, mais la sous liste entière.
    Tu ne dois donc pas supprimer via la variable "iterator" qui correspond à la liste globale, mais via un autre iterator qui correspondra à la sous liste courante.

  11. #11
    Membre du Club Avatar de mobi_bil
    Profil pro
    Inscrit en
    Février 2009
    Messages
    242
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 242
    Points : 52
    Points
    52
    Par défaut
    Bonjour à vous tous et merci pour votre aide.

    Djobird>> Merci, je l'ai trouvé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Iterator<List<Double>> iterator=double_liste.iterator();
    List<Double> ls=iterator.next();
    Iterator <Double> iterat=ls.iterator();
     
    	while(iterat.hasNext())
    	    {
    	    Double i=iterat.next();
    	    // Traitement;   
    	    iterat.remove();                   	   
     
    	     }
    Comme ça, le code marche très bien.

    Ce que je veux maintenant, c'est de connaître la taille de chaque liste.

    Supposons qu'on a 3 listes de type " List<Double> " inclues dans une "LinkedList < List <Double> > ", chacune des 3 trois listes contient 2 éléments.

    Lorsque j'essaie d'afficher par exemple le nombre d'éléments de la première liste, il m'affiche 6 (nombre total de tous les éléments de la liste qui contient les trois listes ) alors que la première liste contient seulement 2 éléments.

    Merci pour votre aide?

Discussions similaires

  1. Réponses: 9
    Dernier message: 05/06/2015, 16h48
  2. Réponses: 1
    Dernier message: 15/03/2010, 21h53
  3. [JDOM] Exception:Exception in thread "main" java.util.ConcurrentModificationException
    Par solawe dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 10/06/2009, 18h33
  4. erreur No Converter for type java.util.Date found
    Par gefrey54 dans le forum JSF
    Réponses: 2
    Dernier message: 07/07/2008, 17h09
  5. Réponses: 5
    Dernier message: 02/06/2008, 12h21

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