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

Langage Java Discussion :

Eviter une double boucle


Sujet :

Langage Java

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 8
    Points
    8
    Par défaut Eviter une double boucle
    Bonjour au forum !

    Je planche actuellement sur un projet, et j'ai un temps d'exécution beaucoup trop élevé.
    J'ai identifié la cause comme étant une méthode qui effectue une double boucle sur un ArrayList<List<String>>().

    Voici mon code que je vous décrirai ensuite :

    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
     
    public List<List<String>> filteredMaterial(List<List<String>> material) {
            List<String> filteredMaterialTemp = new ArrayList<>();
            FMaterial = new ArrayList<>();
            for (int i = 0; i < material.size(); i++) {
     
    // On parcourt material pour éviter les doublons de "valeur" pour un même "name" 
     
                for (int j = i + 1; j < material.size(); j++) {
                    if (material.get(i).name.equals(material.get(j).name) && !material.get(i).valeur.equals(material.get(j).valeur)) {
                        FMaterial.add(material.get(i));
                    }
                }
            }
            System.out.println("Taille du materiel " + material.size());
    // retourne 106 000
            return FMaterial;
        }
    Je fais donc une double boucle pour ne garder que les éléments qui existent au moins 2 fois sous le même "name" avec une "valeur" différente.
    J'aimerai éviter cette double boucle.
    Une idée?

    D'avance merci !!!

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Tout d'abord ton code est étrange : material est une List<List<String>>, or tu fais appel à des attributs name et valeur sur material.get(i), donc sur une List<String>, une interface qui n'a pas (et ne risque pas d'avoir) ces attributs.

    Ça me semble difficile de dédoublonner une liste de liste en une seule boucle.

    C'est une liste de propriétés (name + valeur), ou une liste de listes de String ?
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    commence déjà par faire un seul get(i) dans la première boucle et un seul get(j) dans la deuxième boucle ... il n'y a pas de petits profits (et en plus on comprendra mieux).
    ensuite opérer sur une copie triée de material ?
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 9
    Points : 8
    Points
    8
    Par défaut
    Merci pour vos réponses !

    Tout d'abord, oui j'ai mis name et valeur pour simplifier (au lieu de get(3) et get(5)).
    Sinon je crois avoir trouver une méthode. Je fais une Hashmap (name, Hashmap(valeur, index de la boucle)).
    J'ai fais des tests et ça a résolu mon problème complètement.
    Voici le nouveau code si jamais cela peut être d'une quelconque utilité.

    Ancien code :
    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
     
    public List<List<String>> filteredMaterial(List<List<String>> material) {
       List<String> filteredMaterialTemp = new ArrayList<>();
            FMaterial = new ArrayList<>();
            for (int i = 0; i < material.size(); i++) {
                if (!material.get(i).get(5).equals("NA")) {
                    for (int j = i + 1; j < material.size(); j++) {
                        if (material.get(i).get(3).equals(material.get(j).get(3))) {
                            if (!material.get(j).get(5).equals("NA")) {
                                if (!material.get(i).get(5).equals(material.get(j).get(5))) {
                                    FMaterial.add(material.get(i));
                                }
                            }
                        }
                    }
                }
            }

    Solution :
    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
     
    public List<List<String>> filteredMaterial(List<List<String>> material) {
            Hashtable<String, Hashtable> filteredMaterial = new Hashtable<String, Hashtable>();
            FMaterial = new ArrayList<>();
            for (int i = 0; i < material.size(); i++) {
                String key = material.get(i).get(3);
                String value = material.get(i).get(5);
                if (filteredMaterial.containsKey(key)) {
                    filteredMaterial.get(key).put(value, i);
                } else {
                    Hashtable temp = new Hashtable();
                    temp.put(value, i);
                    filteredMaterial.put(key, temp);
                }
            }
            Enumeration keys = filteredMaterial.keys();
            while (keys.hasMoreElements()) {
                String name = (String) keys.nextElement();
                if (filteredMaterial.get(name).size() > 1) {
                    Enumeration keys2 = (filteredMaterial.get(name)).keys();
                    while (keys2.hasMoreElements()) {
                        int idx = (int) filteredMaterial.get(name).get(keys2.nextElement());
                        FMaterial.add(material.get(idx));
                    }
                }
            }
            return FMaterial;
        }

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Utilises une HashMap, plutôt qu'une HashTable : tu gagneras encore en performances (la HashTable est synchronized, ce qui ne sert à rien ici, et le fait qu'elle interdise les nulls n'a pas d'utilité non plus à priori).

    Ensuite, plutôt que de parcourir les clefs et de faire des get(), autant parcourir le EntrySet : tu gagneras aussi en performances (en plus, ça t'évitera de faire plusieurs get sur la même clef).

    Pour le reste, çà me semble bien compliqué pour faire du dédoublonage, mais je n'ai fait que survoler le code. La solution par HashMap est en effet une bonne voie, mais c'est cette notion d'index et le (filteredMaterial.get(name).size() > 1 qui m'étonne (sans parler qu'il manque quelque chose pour que ça compile à priori, ou alors c'est pire, la variable FMaterial n'est pas déclarée au bon endroit).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 13/12/2011, 16h55
  2. Quitter une double boucle while
    Par sirop-de-menthe dans le forum MATLAB
    Réponses: 3
    Dernier message: 13/05/2011, 23h05
  3. [PIL] temps perdu sur une double boucle
    Par graminou dans le forum Calcul scientifique
    Réponses: 10
    Dernier message: 08/12/2008, 13h27
  4. Eviter une double jointure de la même table ?
    Par Jérémy197 dans le forum Requêtes
    Réponses: 4
    Dernier message: 27/10/2008, 15h01
  5. Sortir d'une double boucle FOR-END
    Par azboul dans le forum MATLAB
    Réponses: 4
    Dernier message: 05/12/2007, 11h07

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