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 :

Compter les occurences de lignes et non de mots provenant d'un fichier texte


Sujet :

avec Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2020
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2020
    Messages : 3
    Par défaut Compter les occurences de lignes et non de mots provenant d'un fichier texte
    Bonjour à tous,

    Je commence à apprendre le langage Java et je ne trouve pas de solution à mon problème. Je dois compter le nombre d'occurrences de lignes identiques issues d'un fichier texte. J'ai trouvé un début de solution avec le code ci-dessous mais cela me compte le nombre d'occurrences de mots alors que je souhaite identifier et incrémenter les lignes identiques. J'ai tenté une autre approche avec Collector.GroupBy mais alors là, j'ai des erreurs de partout. Est-ce que quelqu'un pourrait m'indiquer une piste à suivre svp ? Merci d'avance pour votre aide.

    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
     
     
     
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
     
    public class AnalyticsCounterV2 {
    	private static final String FILENAME = "C:\\\xxx.txt";
     
    	public static void main(String[] args) throws FileNotFoundException, IOException {
     
    		Map list = new HashMap();
     
    		try (BufferedReader br = new BufferedReader(new FileReader(FILENAME))) {
    			StringBuffer sb = new StringBuffer();
    			String line = br.readLine();
     
    			while (line != null) {
    				String[] words = line.split(" "); 
    				for (int i = 0; i < words.length; i++) {
    					if (list.get(words[i]) == null) {
    						list.put(words[i], 1);
    					} else {
    						int newValue = Integer.valueOf(String.valueOf(list.get(words[i])));
    						newValue++;
    						symptomslist.put(words[i], newValue);
    					}
    				}
    				sb.append(System.lineSeparator());
    				line = br.readLine();
    			}
    		}
    		HashMap<String, String> sorted = new HashMap<String, String>(list);
    		for (Object key : sorted.keySet()) {
    			System.out.println(key + " : " + list.get(key));
    		}
    	}
    }

  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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Salut,

    1. Si tu dois compter des lignes, il est inutile de les diviser en mots
    2. Il y a différent moyen de lire des lignes depuis un fichier texte. La méthode que tu utilises est obsolète, parce qu'il existe des méthodes depuis Java 7 et Java 8 qui simplifient ce type de traitement. La classe java.nio2.file.Files par exemple, avec java.nio2.file.Path et java.nio2.file.Paths.

      1. Si on veut charger toutes les lignes en mémoire, dans une liste :
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        List<String> lines = Files.readAllLines(Paths.get(FILENAME));
      2. Si on veut traiter les lignes sans avoir à tout charger en mémoire (si le fichier est très grand) :
        Code : Sélectionner tout - Visualiser dans une fenêtre à part
        1
        2
        3
        Files.lines(Paths.get(FILENAME)).forEach(line-> {
        	// traitement de la ligne par la variable line
        });
        Pour le coup cette méthode ne simplifie pas le comptage des doublons que tu veux faire.

    3. Pour compter les doublons, le plus simple est de passer par une Map, un type d'objet qui permet d'associer des clefs et des valeurs. En clef, on mettra une ligne, et en valeur le nombre d’occurrences de cette ligne.

      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
      List<String> lines = Files.readAllLines(Paths.get(FILENAME));
       
      Map<String, Long> compteurs = new HashMap<>();
      for(String line : lines) {
       
      	if ( compteurs.containsKey(line) ) { 
      		// si la ligne contient déjà la ligne, on incrémente le compteur qui est associé
                      compteurs.put(line, compteurs.get(line)+1);
              }
              else {
      	       // sinon on ajoute l'association en initialisant le compteur à 1
      	       compteurs.put(line, 1L);
              }
       
      }
      On peut simplifier ce code en utilisant la méthode compute de Map :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      List<String> lines = Files.readAllLines(Paths.get(FILENAME));
      Map<String, Long> compteurs = new HashMap<>();
      for(String line : lines) {
       
      	compteurs.compute(line, (l,c)-> c==null?1:c+1);
       
      }
      ou la méthode merge :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      List<String> lines = Files.readAllLines(Paths.get(FILENAME));
      Map<String, Long> compteurs = new HashMap<>();
      for(String line : lines) {
       
      	compteurs.merge(line, 1L, (compteur, increment)->compteur+increment);
       
      }
    4. On peut utiliser la méthode groupBy, pour simplifier encore :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      List<String> lines = Files.readAllLines(Paths.get(FILENAME));
      Map<String, Long> compteurs = lines.stream()
      		                   .collect(Collectors.groupingBy(line-> line,
      		    		            Collectors.counting())
      );
      ou encore :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      List<String> lines = Files.readAllLines(Paths.get(FILENAME));
      Map<String, Long> compteurs = lines.stream()
      		                   .collect(Collectors.groupingBy(Function.identity(),
      		    		            Collectors.counting())
      );


    A noter que la définition de ton fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private static final String FILENAME = "C:\\\xxx.txt";
    stipule que le nom du fichier commence par le caractère \x qui n'existe pas en Java.
    Pour t'éviter d'avoir à échapper les antislashs et donc de risquer ce genre d'erreur, tu peux simplement utiliser des slashes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private static final String FILENAME = "C:/xxx.txt";
    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
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2020
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2020
    Messages : 3
    Par défaut
    Merci beaucoup Joël,

    J'avais cherché un peu partout et commencé à construire mon code en fonction de mes recherches mais alors là, ce que tu m'as expliqué est vraiment plus simple et surtout plus concis. Merci beaucoup pour ton aide.
    Du coup, j'avais une autre petite question : si je veux obtenir une liste ligne par ligne, est-ce que ce que j'ai fait est aussi obsolète ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     sb.append(System.lineSeparator());  
    line = br.readLine();
    J'ai aussi lu qu'on ne peut pas ensuite sortir un fichier texte issu d'une Map qui serait triée par ordre alphabétique car les Map ne le permettent pas : est-ce que tu pourrais juste me le confirmer sans vouloir trop t'embêter à nouveau ?

    Encore une fois merci vraiment pour tout.
    Bien à toi

  4. #4
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par lanasandra Voir le message
    Du coup, j'avais une autre petite question : si je veux obtenir une liste ligne par ligne, est-ce que ce que j'ai fait est aussi obsolète ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     sb.append(System.lineSeparator());  
    line = br.readLine();
    Je ne suis pas entré dans tout le détail de ton code effectivement. Si tu cherches à construire une chaîne qui concatène toutes les lignes, on peut faire ce que tu as fait, en résumé :

    Créer un StringBuffer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StringBuffer sb = new StringBuffer();
    Parcourir les lignes en ajoutant au StringBuffer en intercalant un séparateur de ligne par sb.append(System.lineSeparator()).

    Seulement il manque une chose indispensable dans ton code d'origine : ajouter chaque ligne dans le StringBuffer.

    Ensuite, StringBuffer n'est pas obsolète : simplement cette classe est dite "synchronisée". Elle est prévue pour fonctionner en multithread. Ce qui n'est pas utile dans ton cas. L'équivalent en monothread est StringBuilder et s'utilise exactement de la même manière. A une époque, choisir un StringBuilder était avantageux par rapport à un StringBuffer lorsqu'on était en monothread, pour des raisons de performances. Je n'ai pas d'informations sur les différences de performances sur des environnements récents avec des versions de jvm récentes qui sont beaucoup plus rapides qu'à une époque. Mais bon, autant utiliser un StringBuilder quand un StringBuffer n'est pas nécessaire.

    Ensuite, il y a des moyens beaucoup plus simples de faire la même chose, d'autant plus qu'avec le code que je t'ai donné, on a une liste de lignes désormais.

    Tout d'abord, s'il s'agit juste de l'envoyer dans la console, on peut simplement parcourir les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for(String line : lines) {
        System.out.println(line);
    }
    Ou encore le faire directement sans la boucle for, avec un code très concis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lines.forEach(System.out::println);
    On peut même le faire de la même manière en lisant le fichier lignes à lignes sans le charger dans une List en mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Files.lines(Paths.get(FILENAME)).forEach(System.out::println);
    On peut même écrire les lignes dans un fichier directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Files.write(Paths.get(FILENAME), lines);
    On peut faire des choses similaires à partir d'une Map, mais j'en parlerai après avoir répondu à ta seconde question.

    [QUOTE=lanasandra;11306241]

    J'ai aussi lu qu'on ne peut pas ensuite sortir un fichier texte issu d'une Map qui serait triée par ordre alphabétique car les Map ne le permettent pas : est-ce que tu pourrais juste me le confirmer ]

    Quand on parle de Map, on sous entends parler d'objets de classe qui implémente l'interface java.util.Map. La plus couramment utilisée c'est la HashMap. Et l'une de ses caractéristiques et qu'elle ne garantit aucun ordre particulier (c'est dû au stockage optimisé par une table de hashage dont le but est d'optimiser l'opération pour retrouver une valeur en fonction d'une clef.

    Mais il existe des implémentations de l'interface Map qui sont "ordonnées" :

    • java.util.LinkedHashMap garantit que l'ordre des associations (donc des clefs) respectent l'ordre d'insertion
    • java.util.TreeMap permet d'avoir un tri selon l'ordre qu'on veut, donc alphabétique par exemple. On peut même trier selon les valeurs.


    Pour la LinkedHashMap, dans les cas où je crée explicitement la HashMap, il suffit de remplacer la partie instanciation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Map<String, Long> compteurs = new LinkedHashMap<>();
    Pour le "grouping", il faut indiquer au Collector une fabrique (dans le code suivant c'est le LinkedHashMap::new:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Map<String, Long> compteurs = list.stream()
    		    .collect(Collectors.groupingBy(Function.identity(),
    		    	                           LinkedHashMap::new,
    		    	                           Collectors.counting())
    );
    Pour avoir une Map triée, le plus simple est de créer une nouvelle TreeMap puis d'ajouter toutes les associations de la Map d'origine dedans :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TreeMap<String, Long> compteurstri = new TreeMap<>();
    compteurstri.putAll( compteurs );
    Ici l'ordre de tri est l'ordre de tri (par défaut) dit naturel des clefs, donc de String. Cela ressemble à un tri alphabétique, mais ce n'est pas tout à fait exactement un tri alphabétique au sens commun. Ce tri se base sur l'ordre des codes de caractères. Par exemple, les accents ne seront pas triés selon un ordre correspondant à une attente classique (le f suit le e, mais le é, le è etc ne sont pas entre le e et le f, du coup, les chaînes comprenant des mots avec accents ne seront pas correctement triées). Il y a également le problème des nombres : avec un tri naturel, Machin10 est avant Machin2 alors que naturellement on s'attend à ce que Machin10 soit plutôt après.

    Pour configurer l'ordre qu'on veut, on peut indiquer un Comparator en paramètre de l'instanciation de la TreeMap.

    Pour trier des chaînes en tenant compte des accents, on peut utiliser un Comparateur spécial, implémenté par la classe Collator.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TreeMap<String, Long> compteurstri = new TreeMap<>(Collator.getInstance());
    Pour le tri tenant compte de l'ordre des caractères, c'est plus compliqué. Si tu en as besoin, je te dirais comment faire.

    Enfin, pour le parcours et l'éventuel sortie en console, ou vers un fichier.

    Je t'ai dit qu'on pouvait procéder de façon similaire à une List. On fait ça en prenant la liste des associations de la map. Les associations sont représentées par la classe Map.Entry qui a deux méthodes : une pour récupérer la clef et une pour récupérer la valeur.

    Donc, par exemple, pour afficher les lignes avec leur compteur associé (concaténation de la ligne, de :, puis du compteur)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for( Map.entry<String,Long> compteur : compteurstri.entrySet() ) {
        System.out.println(compteur.getKey() + ": " + compteur.getValue()); 
    }
    On peut retransformer la map en liste, ce qui permet de l'écrire dans un fichier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List<String> finallines = compteurstri.entrySet()
    				.stream()
    				.map(entry-> entry.getKey()+": "+entry.getValue())
    				.collect(Collectors.toList());
    Files.write(Paths.get(OUTPUTFILENAME), finallines);
    Si on veut ne retrouver que les lignes sans la valeur, on peut passer directement par la liste des clefs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Files.write(Paths.get(OUTPUTFILENAME), compteurs.keySet());
    Ceci permet d'obtenir le fichier dédoublonné sans altération de l'ordre si compteurs est une LinkedHashMap.

    On peut même exclure les lignes qui ne sont pas en double (ou plus), :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    List<String> finallines = compteurstri.entrySet()
    				.stream()
                                    .filter( entry-> entry.getValue()>1 ) // on ne garde que les lignes dont le compteur est supérieur à un
    				.map(entry-> entry.getKey()+": "+entry.getValue())
    				.collect(Collectors.toList());
    Files.write(Paths.get(OUTPUTFILENAME), finallines);
    Si on veut ne retrouver que les lignes sans la valeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    List<String> finallines = compteurstri.entrySet()
    				.stream()
                                    .filter( entry-> entry.getValue()>1 ) // on ne garde que les lignes dont le compteur est supérieur à un
    				.map(Map.entry::getKey) // on récupère que la clef (donc la ligne)
    				.collect(Collectors.toList()); // on transforme en List
    Files.write(Paths.get(OUTPUTFILENAME), finallines);
    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.

  5. #5
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2020
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2020
    Messages : 3
    Par défaut
    Mille mercis !! J'ai suivi tous les conseils et tout marche. J'ai juste rajouté un try et catch.
    Voici mon code finalisé grâce à ces précieux conseils :
    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 class AnalyticsCounterV10 {
     
    	private static String FILENAME = "C:/Users/sandr/Desktop/symptoms.txt";
    	private static String OUTPUTFILENAME = "C:/Users/sandr/Desktop/FileResult.txt";
     
    	public static void main(String[] args) throws Exception {
     
    		try {
    			List<String> lines = Files.readAllLines(Paths.get(FILENAME));
    			Map<String, Long> compteurs = lines.stream()
    					.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
     
    			TreeMap<String, Long> compteurstri = new TreeMap<>();
    			compteurstri.putAll(compteurs);
     
    			List<String> finallines = compteurstri.entrySet().stream()
    					.map(entry -> entry.getKey() + ": " + entry.getValue()).collect(Collectors.toList());
    			Files.write(Paths.get(OUTPUTFILENAME), finallines);
     
    		}
     
    		catch (IOException e) {
    			e.printStackTrace();
     
    		}
    	}
    }
    Encore un grand merci Joël pour ces explications ultra claires.
    Bien à toi

  6. #6
    Membre averti Avatar de BBornier
    Homme Profil pro
    Etudiant en dev Java
    Inscrit en
    Mars 2021
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Etudiant en dev Java

    Informations forums :
    Inscription : Mars 2021
    Messages : 15
    Par défaut Question sur la POO sur ce sujet
    Bonjour,

    Je me permets de déterrer ce topic car il est toujours d'actualité :
    grand débutant en programmation java et faisant visiblement le même parcours de formation Java que Lanasandra, je me prenais la tête pour comprendre comment résoudre le problème de ce projet. Tout d'abord Joël, grand merci pour tous ces éléments de réponses ! C'est merveilleux ! En revanche je ne peux pas dire que j'ai le niveau pour le moment pour écrire ce type de solution .

    je précise que l'énoncé du projet est exactement le même, à savoir lire un fichier de symptômes avec des doublons à trier et créer un fichier dans lequel les occurrences sont comptabilisées.
    J'ai écris le code comme suit en m'inspirant évidemment de vos échanges, sans passer par la HashMap mais directement avec la TreeMap. J'ai gardé pas mal de choses en commentaires pour m'aider à bien comprendre tout le processus et de quoi faire ma javadoc. Est-ce bien ou est-ce que je saute des étapes ?


    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
     
    public class AnalyticsCounterV2 {
     
    	public static void main(String[] args) throws IOException {
    		try {
     
    		/*
    		 * Cette ligne charge toutes les lignes en mémoire, dans une liste.
    		 */
    		List<String> lines = Files.readAllLines(Paths.get("Project02Eclipse/symptoms.txt"));
     
    		/*
    		 * Ici, on compte les doublons grâce à la Map. en paramètres, Clé (ligne) et
    		 * valeur (nb d'occurrences). Avoir instancié "TreeMap" permet de sortir les
    		 * symptômes dans l'ordre alphabétique en affichage de console.
    		 * Utilisation du comparateur avec la classe Collator. Cela prendra en compte les accents 
    		 * (si l'on veut une version du fichier result.out en français par exemple).
    		 * 
    		 */
     
    		TreeMap<String, Long> comptTri = new TreeMap<>(Collator.getInstance());
     
    		for (String symptoms : lines) {
     
    			if (comptTri.containsKey(symptoms)) {
    				// si la ligne contient déjà la ligne, on incrémente le compteur qui est associé :
    				comptTri.put(symptoms, comptTri.get(symptoms) + 1);
    			} else {
    				// sinon on ajoute l'association en initialisant le compteur à 1 (1L étant pour le type long) :
    				comptTri.put(symptoms, 1L);
    			}
    		}
    		// Sortir la liste des symptômes dans la console :
    		Files.lines(Paths.get("Project02Eclipse/symptoms.txt")).forEach(System.out::println);
    		// Sortir la TreeMap en brut dans la console :
    		System.out.println(comptTri);
     
    		/*
    		 * Cette ligne permet d'écrire dans le fichier resultV2.out les résultats.
    		 */
    		Files.write(Paths.get("resultV2.out"), lines);
     
    		/*
    		 * Cette partie permet d'écrire dans le fichier resultV3.out les résultats triés, à la ligne et avec le nb d'occurrences.
    		 */
    		List<String> finallines = comptTri.entrySet()
    				.stream()
    				.map(entry-> entry.getKey()+": "+entry.getValue())
    				.collect(Collectors.toList());
    		Files.write(Paths.get("resultV3.out"), finallines);
     
     
    		} catch(IOException e) {
    			e.printStackTrace();
     
    		}
    	}
    }
    Mes questions :
    - Il nous est demandé de faire en sorte que le code corresponde aux principes de la programmation orientée objet. J'imagine donc que cela demande de créer d'autres classes avec leurs méthodes. Ce code étant déjà très concis, est-il possible de faire autrement (créations et utilisation d'interfaces, créations de classes à part dont les méthodes seront invoquées dans le main) ? plus décomposé d'une certaine manière ?
    - En plus du main (AnalyticsCounter.java) à corriger, nous avions une classe ReadSymptomDataFromFile.java et une interface avec la méthode GetSymptoms (elle même implémentée dans le ReadSymptomDataFromFile.java). Mais là j'ai eu beau me creuser, je ne sais pas comment appeler/faire fonctionner dans le main ce code. La solution que j'ai trouvé ici me convient parfaitement mais je veux vraiment comprendre comment ça fonctionne et répondre au mieux à ce qui m'est demandé. A savoir que ces deux fichiers sont des pistes pour la correction :

    Le Main d'origine à corriger que j'avais déjà bien débroussaillé pour pas dire avoir enlevé une très grosse partie:
    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
     
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
     
    public class AnalyticsCounter {
     
    	public static void main(String args[]) throws Exception {
     
    		try {
    		/* Lecture du fichier symptoms.txt via le BufferedReader */
    		BufferedReader reader = new BufferedReader(new FileReader("Project02Eclipse/symptoms.txt"));
    		String line = reader.readLine();
     
    		//HashMap<String, Integer> occurrences = new HashMap<String, Integer>();
     
     
    		int i = 0;
    		while (line != null) {
    			i++;
    			System.out.println("symptom : " + line);
     
    			line = reader.readLine(); // get another symptom
    		}
     
    		// next generate output
    		FileWriter writer = new FileWriter("result.out");
    		writer.write("\n");
    		writer.close();
    		reader.close();
     
    		} catch  (IOException e) {
    			e.printStackTrace();
    		}
    	}
    }
    Le début de correction fourni avec l'énoncé :
    Code Java : 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
     
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
     
    /**
     * Simple brute force implementation
     *
     */
    public class ReadSymptomDataFromFile implements ISymptomReader {
     
    	private String filepath;
     
    	/**
             * 
             * @param filepath a full or partial path to file with symptom strings in it, one per line
             */
    	public ReadSymptomDataFromFile (String filepath) { // constructeur
    		this.filepath = filepath;
    	}
     
     
    	@Override
    	public List<String> GetSymptoms() {
    		ArrayList<String> result = new ArrayList<String>();
     
    		if (filepath != null) {
    			try {
    				BufferedReader reader = new BufferedReader (new FileReader(filepath));
    				String line = reader.readLine();
     
    				while (line != null) {
    					result.add(line);
    					line = reader.readLine();
    				}
    				reader.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
     
    		return result;
    	}
     
    }

    Et enfin, l'interface comme piste de correction également :
    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
     
    import java.util.List;
     
    /**
     * Anything that will read symptom data from a source
     * The important part is, the return value from the operation, which is a list of strings,
     * that may contain many duplications
     * 
     * The implementation does not need to order the list
     * 
     */
    public interface ISymptomReader {
    	/**
             * If no data is available, return an empty List
             * 
             * @return a raw listing of all Symptoms obtained from a data source, duplicates are possible/probable
             */
    	List<String> GetSymptoms ();
    }
    Du coup, quelles seraient les bonnes pratiques ? et surtout comment utiliser la classe ReadSymptomDataFromFile ?

    A savoir que dans toutes mes recherches j'étais tombé sur la notion de TreeMap (bien meilleure qu'une HashMap dans le cadre de ce projet), c'est ce qui m'a permis par extension d'arriver sur ce super topic.

    Merci pour votre aide ^^.

Discussions similaires

  1. Compter les occurences dans un tableau trié
    Par degseb dans le forum Pascal
    Réponses: 2
    Dernier message: 10/01/2008, 16h34
  2. compter les occurences dans un fichier avec fgetc
    Par deathsurfer dans le forum C
    Réponses: 21
    Dernier message: 21/01/2007, 13h44
  3. Compter les occurences dans relation "n vers n"
    Par yamayo dans le forum Access
    Réponses: 3
    Dernier message: 02/10/2006, 18h54
  4. [FAQ] compter les occurences d'une chaîne dans un fichier
    Par cafeine dans le forum Contribuez
    Réponses: 3
    Dernier message: 25/07/2006, 11h21
  5. Compter les occurences d'un car dans une chaine/variable
    Par sherlockfr dans le forum Windows
    Réponses: 2
    Dernier message: 10/11/2005, 07h48

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