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

  1. #1
    Nouveau 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
    Points : 1
    Points
    1
    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 : 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,

    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
    Nouveau 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
    Points : 1
    Points
    1
    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 : 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
    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
    Nouveau 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
    Points : 1
    Points
    1
    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 à l'essai 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
    Points : 14
    Points
    14
    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 ^^.

  7. #7
    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,


    1. Au sujet de l'aspect Map, HashMap vs TreeMap, etc.
      Dans la question d'origine, il est question de compter des occurrences de lignes, donc en gros, on cherche à obtenir différentes valeurs, et pour chacune de ces valeurs, le nombre d'occurrences de ces valeurs. genre, j'ai des L1, L2, L3..., en résultat je voudrais nombre de L1 = 5, nombre de L2 = 3, nombre de L3 = 1, etc. D'où l'intérêt d'une Map qui permet d'associer les valeurs et leur compte.
      S'il ne s'agit que d'obtenir une liste dédoublonnée un Set sera plus adapté.
    2. HashMap versus TreeMap, (ou HashSet vs TreeSet ).
      Une TreeMap n'a d'intérêt que si on veut trier les valeurs. Sinon, une HashMap est préférable car plus performante. Mais j'ai cru voir quelque part dans ton énoncé le mot "trié", donc pour ça une TreeMap serait effectivement plus adaptée. A noter que si on veut conserver l'ordre d'origine, c'est plutôt une LinkedHashMap (ou LinkedHashSet si on ne veut pas compter) qu'il faudra utiliser.
    3. Au sujet de l'aspect POO
      C'est la partie compliquée de la question En dehors de la définition de base d'un objet (des attributs et des méthodes), la POO, c'est des principes d'architecture. Cela peut aller loin, mais si tu es débutant, tu n'es pas forcément obligé de suivre tous les principes. D'ailleurs, il y a toujours des débats sur ça qui est objet, ça qui ne l'est pas, même si ça y ressemble... Ce n'est pas que c'est une appréciation personnelle, c'est plutôt que pour être purement objet, c'est compliqué naturellement, donc souvent on croit faire de l'objet, mais ça ne l'est pas complètement. Faire des classes, des interfaces, ça ne suffit pas, mais j'imagine que pour débuter c'est déjà ça.
      Personnellement, je pense qu'on peut se baser sur trois principes de base :
      • les objets doivent être des boites noires : les autres objets qui les manipulent ne doivent pas avoir à savoir comment ils fonctionnent à l'intérieur, et ne doivent pas avoir à suivre des règles d'utilisation particulières (comme par exemple, appeler d'abord cette méthode, puis celle-là, ou devoir récupérer des informations spécifiques (qu'on ne devrait pas pouvoir en théorie d'ailleurs récupérer), en faire quelque chose à l'extérieur, pour avoir le résultat final. En particulier, en cas d'interface, la manipulation ne devrait passer exclusivement que par l'interface, sauf à l'instanciation éventuellement, où il est nécessaire de passer des paramètres spécifiques au constructeur. Un truc à éviter, ce sont les changements d'état qui imposeraient d'appeler les méthodes d'un objet dans un ordre particulier, voire qui mettrait l'objet dans un état foireux si on n'appelle pas une méthode particulière.
      • ensuite, les principes d'héritage
      • et le polymorphisme

      Sur ces deux derniers points, ils sont dépendants du langage (des langages permettent le multi héritage, d'autres non, des langages intègrent certains types de polymorphisme, d'autres non, etc). Après, on pourrait ajouter qu'il faut éviter la tendance au procédural (même si ça simplifie souvent certaines choses, et que même le JDK ne s'en prive pas) : la manière la plus simple d'y parvenir est de ne pas avoir de "static", sauf si c'est absolument obligatoire. Normalement, pour les méthodes, la seule qui soit obligatoire, c'est la méthode main(String[] args), pour exécuter le programme. Toute autre méthode statique est à proscrire. Pour les attributs, se limiter au static final qui permettront de déclarer des "constantes" (des valeurs fixes pendant le runtime, en particulier si on a besoin de les utiliser à plusieurs endroits, pour faciliter leur modification entre plusieurs exécutions). Après, bien sûr tous les principes de la programmation structurée sont à suivre.

      En ce qui concerne l'architecture de la classe ReadSymptomDataFromFile, il me semble au moins que ça respecte le premier principe.
      Pour bien comprendre ce que ça signifie, imagine qu'il existe une autre implémentation, genre ReadSymptomDataFromDB : pour récupérer les données, tu utiliseras le même code, les deux classes seront interchangeable, et il est même préférable de manipuler d'objet via son interface, sans avoir à se préoccuper d'où viennent ces listes de String. Pour l'héritage et le polymorphisme, c'est plus difficile à mettre en œuvre avec une seule méthode, une seule classe, et une seul instance de cette classe (la classe main ne compte pas).

      Enfin, dans ce que tu as à réaliser, c'est un peu difficile d'imaginer ce qu'on attend de toi. Il y a probablement beaucoup de façons d'aborder la chose, mais là simplicité de ce qu'il y a faire (enfin, je n'ai pas l'énoncé original complet à priori, donc encore plus difficile). Une idée qui me vient, c'est de traiter le dédoublonnage et le tri à part, dans des classes dédiées (c'est le commentaire "that may contain many duplications" qui me fait penser à ça.

      Je vais éviter de te donner le code final, ce n'est pas le but du forum, mais de concrétiser l'idée par un canevas exemple :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
       
      public class SymptomDataDeduplicate implements ISymptomReader  {
       
          public SymptomDataDeduplicate(ISymptomReader  symtoms) {
          }
       
          public List<String> GetSymptoms () {
                // ici on récupère les data dans l'objet passé en argument du constructeur et on retourne une version dédoublonnée de cette liste
          }
       
      }
      Pareil pour une SymptomDataSorter...

      Cependant, je dois t'avouer que je ne ferais probablement pas comme ça dans un programme. Il y a des moyens plus souple et plus facile à manipuler pour faire ça de façon pour rapide sans se coltiner une instanciation. Mais le but ici est pédagogique je suppose : l'intérêt ici et de te montrer la souplesse que l'objet permettra, qu'on peut comprendre avec une séquence par exemple :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      ISymptomReader symptoms = new ReadSymptomDataFromFile( filepath );
      ISymptomReader deduplicatedSymptoms  = new SymptomDataDeduplicate(symptoms),
      ISymptomReader sortedSymptoms  = new SymptomDataSorter(deduplicatedSymptoms, comparator),
       
      System.out.println( sortedSymptoms.GetSymptoms() );
      Tu peux imaginer qu'on pourrait enchaîner comme ça, dans un ordre ou un autre, différentes classes qui font tel ou tel traitement (de liste de data), par l'intermédiaire d'une interface unique, sans aucune n'est besoin de savoir ce que la précédente à fait, ou ce que la suivante fera. Et tu dois voir qu'on peut changer la première ligne pour lire des symptoms depuis une base de données par exemple, sans avoir à modifier la suite.

      Ce qui me gêne par ailleurs c'est le nom de l'interface : le reader semble indiquer que les classes d'implémentations sont censés lire... mais bon d'un autre côté, c'est aussi acceptable de lire des datas depuis un fichier, ou de les lire depuis un ISymptomReader. Mais, normalement, on ne devrait pas avoir à manipuler des datas qu'on a lues ou pas lues, ces data pourraient être générées automatiquement par exemple, mais bon c'est le sujet, il faut le suivre.

      Une autre façon d'aborder l'objet ici serait d'avoir une classe pour représenter des "symptoms", mais l'interface ne prédispose pas à ça, puisque la méthode retourne une liste de String.

      Désolé de ne pas pouvoir t'aider plus que ça.
    4. Pour ta question "je ne sais pas comment appeler/faire fonctionner dans le main ce code."


      Tu as écrit dans ton premier extrait de code
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      List<String> lines = Files.readAllLines(Paths.get("Project02Eclipse/symptoms.txt"));
      Imagine que tu remplaces cette ligne par :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      List<String> lines = new ReadSymptomDataFromFile("Project02Eclipse/symptoms.txt")).GetSymptoms();
      C'est assez similaire, et donc la suite devrait venir assez facilement, non ?
    5. Il y a d'autres remarques sur le code, qui n'ont pas beaucoup d'importance lorsqu'on débute (comme les conventions d'écriture Java ), d'autres un peu plus (certaines écritures à but pédagogique mais qu'on n'utiliserait plus parce qu'il y a mieux, plus souple, plus performant, plus pratique) et d'autres très importantes (comme la libération de ressources, cf le try-with-resource qui permet de s'acquitter de cette tâche très facilement en écrivant moins de code en plus.
      )

    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.

  8. #8
    Membre à l'essai 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
    Points : 14
    Points
    14
    Par défaut
    WoW ! Merci Joël pour cette réponse très riche !
    Ce qui me donne du coup encore plus l'envie de continuer à apprendre et avancer ^^. Et sans doute plus tard aider de futurs débutants . Je prends bien note de tes explications, c'est vraiment génial.

    1.2. Effectivement le fichier result.out doit contenir et trier la liste des symptômes qui sont listés à la volée dans un autre fichier. La liste doit être dédoublonnée, les doublons comptés et le nombre d'occurrences/doublons affiché en face de chaque symptômes. C'est ce que j'ai réussi à faire avec le TreeMap et les conseils/lignes de code de ton échange avec Lanasandra.

    3. Pour l'énoncé du projet je ne peux malheureusement pas le "divulgacher" sur le forum vu que ce sont des projets accessibles uniquement pour les étudiants en formation avec diplôme à la clé. Par contre je peux toujours te le transmettre en MP pour plus de compréhension si cela t'intéresse. Je pense que déjà ceux qui éprouvent quelques difficultés et se retrouvent ici seront déjà grandement aidés !

    Et oui, je ne cherche pas la réponse immédiate mais surtout comprendre pour pouvoir y arriver. Merci pour le coup de pouce ! Ce qui m'intéresse c'est savoir faire et puis c'est ce qui m'est aussi demandé .
    Je pense que tu as mis le doigt juste là où il fallait lorsque tu parles de but pédagogique et de ce que l'on peut faire avec l'objet. Et l'exemple que tu donnes m'éclaire et me donne une nouvelle compréhension à ce que j'apprends.

    4. Ok, je commence à saisir ^^. Je sens que ça commence à faire son chemin dans ma tête. Cool !

    Merci beaucoup d'avoir pris le temps. Je vais reprendre toutes tes explications à tête reposée et m'y remettre !

  9. #9
    Membre à l'essai 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
    Points : 14
    Points
    14
    Par défaut Soucis avec résultat : @hexadecimal au lieu du résultat attendu
    Hello !

    Je reviens avec mon sujet et mon programme qui a bien avancé, pour ne pas dire quasiment bouclé.
    J'ai donc tout écrit et posé une grande partie dans le main(String[] args). Tout fonctionne à merveille, écriture des résultats triés dans mon fichier avec le nb d'occurrences, dans l'ordre alphabétique, affichage des résultats sur la console nickel. Côté procédural on est bon .

    Sur les conseils d'une étudiante avancée, l'idée est de laisser moins de choses dans le main et de décomposer le code pour être plus POO. J'ai donc décomposé/rangé comme bon me semblait, ce qui me paraissait logique au départ et c'est là que je me perds dans mes appels de classes et de méthodes. j'ai en effet un résultat avec un hexadecimal dans mon fichier au lieu de ma liste triée, ordonnée.
    L'idée de l'exercice étant de bien comprendre l'utilisation des méthodes, des classes, des appels aux méthodes. Et puis au final c'est vraiment ce qui m'est demande

    J'ai donc fait comme suit :
    Mon main

    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
    package com.hemebiotech.analytics;
     
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Map;
    import java.util.TreeMap;
     
    public class AnalyticsCounterV5 {
     
    	public static void main(String[] args) throws IOException {
     
    		FileWriterData finalResult = new FileWriterData();	
    		finalResult.writeSymptomsData();
     
    		/* Appel de la TreeMap et affichage dans la console pour vérifier que l'output est bon. 
    		 * 
    		 * */
    		SortSymptomsData consoleOutput = new SortSymptomsData();
     
    		TreeMap<String, Integer> symptoms = consoleOutput.sortingSymptomsData();
    		for (Map.Entry<String, Integer> entry : symptoms.entrySet())
    			System.out.println("Symptoms : " + entry.getKey() + ": " +entry.getValue());
     
     
    	}
     
    }
    La Classe ReadSymptomDataFromFile écrite de base dans le sujet de l'exercice et implémente l'interface ISymptomReader (une seule methode, getSymptoms())

    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
    package com.hemebiotech.analytics;
     
    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
    	// Ecriture camelCase pour getSymptoms au lieu de GetSymptoms.
    	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;
    	}
     
     
    	@Override
    	public int sum(int a, int b) {
    		int c = a + b;
    		return c;
    	}
     
    }
    Ma classe SortSymptomsData qui appelle la classe ReadSymptomDataFromFile et ses méthodes . "J'ai rangé" ici la lecture effective de mon fichier et la fonction de tri avec la TreeMap.

    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
    package com.hemebiotech.analytics;
     
    import java.util.List;
    import java.util.TreeMap;
     
    public class SortSymptomsData {
     
    	public TreeMap<String, Integer> sortingSymptomsData() {
     
    		ReadSymptomDataFromFile file = new ReadSymptomDataFromFile("Project02Eclipse/symptoms.txt");
    		file.getSymptoms();
    		List<String> symptomsFile = file.getSymptoms();
     
    		TreeMap<String, Integer> symptomsTri = new TreeMap<>();
    		for (String listSymptoms : symptomsFile) {
    			if (symptomsTri.containsKey(listSymptoms)) {
    				symptomsTri.put(listSymptoms, symptomsTri.get(listSymptoms) + 1);
    			} else {
    				symptomsTri.put(listSymptoms, 1);
    			}
     
    		}
    		return symptomsTri;
    	}
    }
    Ma classe FileWriterData qui va écrire les résultats du tri de la TreeMap dans un fichier "en dur" nommé "results.out"

    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
    package com.hemebiotech.analytics;
     
    import java.io.FileWriter;
    import java.io.IOException;
     
    public class FileWriterData {
     
    	public void writeSymptomsData() throws IOException {
    		try {
     
    			SortSymptomsData symptomsSorting = new SortSymptomsData();
    			FileWriter writer = new FileWriter("resultV5.out");
    			writer.write("Symptoms List " + symptomsSorting);
    			writer.close();
     
    		} catch (IOException e) {
    			e.printStackTrace();
     
    		}
     
    	}
     
    }
    Je précise que mon prof/mentor m'a aidé à rédiger la partie TreeMap dans le main pour afficher le résultat en console.
    En effet, si j'écrivais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    consoleOutput.sortingSymptomsData();
    System.out.println(consoleOutput);
    J'avais comme résultat en sortie de console : com.hemebiotech.analytics.SortSymptomsData@e2d56bf.
    Avec la correction de mon prof, et de l'appel de la TreeMap en tant qu'objet dans le main et de menus changements dans la classe SortSymptomsData, pas de soucis, affichage en console parfait.

    En revanche pour la partie écriture de fichier, ci j'écris ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FileWriterData finalResult = new FileWriterData();	
    finalResult.writeSymptomsData();
    je me retrouve toujours avec quelque chose du genre : Symptoms List com.hemebiotech.analytics.SortSymptomsData@71dac704. Je n'ai toujours pas ma liste de symptômes triés avec leur nombre d'occurrence comme en affichage console. Et j'ai l'impression que c'est autrement plus complexe que l'écriture en console. Je pensais que faire appel aux classes qui contiennent mes méthodes suffirait.

    j'ai eu beau essayer dans tous les sens, et de faire différents appels aux classes je me perds dans mon raisonnement (et je me dis que ma façon de décomposer mon code de base est peut être un peu bord*** finalement ):
    • Est ce que je dois faire appel à ma classe contenant ma TreeMap dans ma classe FileWriterData puis faire appel à cela dans mon main ?
    • Est ce que je dois tout simplement reproduire ce qui a été écrit dans le main ?


    Ex : TreeMap<String, Integer> symptomFile = finalResult.writeSymptomsData();.
    Mais dans ce cas là dans mon FileWriterData je vais devoir écrire public TreeMap<String, Integer> writeSymptomsData() et il va me demander d'écrire return null puisqu'il n'y a pas de valeur à retourner.. Bref je sais que ce n'est pas ça.

    Il doit y avoir encore des notions dans la POO que je ne sais pas encore..
    Merci pour le coup de main ^^.

  10. #10
    Membre à l'essai 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
    Points : 14
    Points
    14
    Par défaut
    Petit Up,

    Si on peut me mettre sur la voie par rapport à mon précédent post

  11. #11
    Membre à l'essai 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
    Points : 14
    Points
    14
    Par défaut
    Solution trouvée, je n'avais pas fait un appel de méthode correct dans ma classe FileWriter. J'ai Terminé ensuite par le bon appel de la méthode de la classe FileWriter dans le main et tout est rentré dans l'ordre . Comme quoi...

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