IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Collection et Stream Java Discussion :

Exercices pratiques, Random, Collection, Map


Sujet :

Collection et Stream Java

  1. #61
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    Comme je l'avais fait au début, j'ai codé tes problèmes en utilisant les nouveautés de java 8 :

    Pour récupérer les 10 jours les plus chaud de l'année :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            List<LocalDate> top10 = map.entrySet().stream()
                    .parallel()
                    .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue()))
                    .limit(10)
                    .collect(
                            ArrayList::new,
                            (list, e) -> list.add(e.getKey()),
                            ArrayList::addAll);

    et pour récupérer le mois le plus chaud de l'année :

    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
            Map<Month, List<Double>> monthTemperatures = map.entrySet().stream()
                    .parallel()
                    .collect(Collectors.groupingBy(
                                    e -> e.getKey().getMonth(),
                                    HashMap::new,
                                    Collectors.mapping(e -> e.getValue(), Collectors.toList())
                            )
                    );
     
            Map.Entry<Month, Double> hottestMonth =
                    monthTemperatures.entrySet().stream()
                            .parallel()
                            .collect(
                                    HashMap<Month, Double>::new,
                                    (mp, entry) -> {
                                        double average = entry.getValue().stream().mapToDouble(x -> x).average().getAsDouble();
                                        mp.put(entry.getKey(), average);
                                    },
                                    HashMap<Month, Double>::putAll
                            ).entrySet().stream().max(Comparator.comparing(item -> item.getValue())).get();

  2. #62
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par benratti Voir le message
    Pour récupérer les 10 jours les plus chaud de l'année :
    Pendant qu'on y est, j'ai voulu m'amuser à éviter les répétitions, ça donne ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List<LocalDate> top10 = map.entrySet().stream()
      .parallel()
      .sorted(Comparator.comparing(Map.Entry::getValue, Comparator.reverseOrder()))
      .limit(10)
      .collect(Collectors.mapping(Map.Entry::getKey, Collectors.toList()));
    J'ai voulu remplacer la 3e ligne par :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      .sorted(Comparator.comparing(Map.Entry::getValue).reversed())
    mais dans ce cas-là l'inférence de type échoue.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #63
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    Ca fonctionne chez moi en précisant les types dans le nom de la classe
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    .sorted(Comparator.comparing(Map.Entry<LocalDate,Double>::getValue).reversed())

  4. #64
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    int numDays = firstDayOfNextMonth.getMonth().length(firstDayOfNextMonth.isLeapYear());
    Je ne pense pas que cette instruction puisque fonctionner

    Ce qui me donne ceci :
    L'affichage n'est pas encore mis en oeuvre car il faut alimenter la SortedMap pour utiliser une classe TestComparator contenant une méthode compare qui comparera les moyennes des 12 mois les unes par rapport aux autres
    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
     
    public Map<YearMonth, Float> genererMoyenneTemperaturesMois() {
            YearMonth firstMonth = new YearMonth(YEAR, 1, chrono);
            Map<YearMonth, Float> hMapMoyTemperatures = new HashMap<>(12);
            // 1. Parcours sur les mois tant qu'on est sur la même année pour récupérer tous les mois
            for (YearMonth mois = firstMonth; mois.getYear() == YEAR; mois = mois.plusMonths(1)) {
                // 1a. Invoquer la méthode calculant la moyenne des températures pour le mois
                //somme / field.getMaximumValue(mois); // Récupérer la plus grande valeur du mois 
                // 1b. Alimenter la Map avec comme cle le mois et comme valeur sa moyenne
                hMapMoyTemperatures.put(mois, moyenne(mois, hMapTemperatures));
            }
            // Afficher le mois dont la moyenne des températures est la plus élevée/la plus basse
     
            return null;
        }

    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
     
    public Float moyenne(YearMonth m, Map<LocalDate, Float> s) {
            LocalDate firstDayOfNextMonth = new LocalDate(YEAR, 2, 2, chrono);
            DateTimeField field = chrono.dayOfMonth(); // le champ permettant de récupérer le jour du mois
            Float somme = 0.f;
            Float moyenne = 0.f;
            // 1. Parcours sur les dates tant qu'on est sur le même mois pour récupérer toutes les températures
            for (LocalDate jour = firstDay; jour.isBefore(firstDayOfNextMonth); jour = jour.plusDays(1)) {
                Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
                // 1a. Alimenter notre Map
                s.put(jour, temperatures);
                // 1b. Ajouter chaque température journalière à la somme des températures 
                somme += temperatures;
                // 1c. Calculer notre moyenne en récupérant TOUS les jours du mois
                moyenne = somme / field.getMaximumValue(m);          
            }
            return moyenne;
        }

  5. #65
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Citation Envoyé par transact Voir le message
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    int numDays = firstDayOfNextMonth.getMonth().length(firstDayOfNextMonth.isLeapYear());
    Je ne pense pas que cette instruction puisque fonctionner
    Je pense que tu as tord.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  6. #66
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Effectivement elle peut fonctionner dans le cas de figure ou Java 8 est utilisé ... mais ce qui n'est pas mon cas puisque je suis resté en Java 7 (pour l'instant) et que j'utilise Joda-Time pour gérer les dates.

  7. #67
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Hum, les exemples que je trouve mentionnent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int numDays = firstDayOfNextMonth.dayOfMonth().getMaximumValue();
    Mais sur un post qqun se plaint qu'il obtient 31 pour le mois de novembre dans son test (qqun lui a suggéré qu'il s'est planté sur la définition de sa date). A vérifier donc. Et a tester aussi si les années bissextiles sont bien prises en compte.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  8. #68
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    D'ailleurs c'est ainsi que je l'utilise
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    DateTimeField field = chrono.dayOfMonth();
    moyenne = somme / field.getMaximumValue(m);
    m correspond au mois passé en paramètre de la méthode moyenne

  9. #69
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Je n'aime pas trop cette méthode pour la moyenne...


    Je ne comprend pas pourquoi tu régénères à nouveau des températures aléatoirement !
    Que tu le fasses pour créer la Map<LocalDate,Float> initiale je peux le comprendre si tu n'as pas de données à aller lire.
    Mais en toute logique c'est du code "temporaire" destiné à être remplacé dans le futur par une méthode qui récupérera de "vrais" données...


    Alors pourquoi régénérer de nouvelle températures aléatoires dans la méthode de calcul de la moyenne ?
    Non seulement cela renverra des résultats bidon même avec de vrai données, mais en plus tu écraseras ces données par les valeurs aléatoires !

    Si tu fais comme cela pour toutes les opérations dont tu as besoin, ton code sera totalement inutilisable le jour où tu travailleras avec de vrai données...



    Bref je vois quelques soucis :
    • Ta méthode genererTemperature() retourne une Map<LocalDate,Float>, et on devrait retrouver cela en paramètre de ta méthode genererMoyenneTemperaturesMois() !
      Ici tu utilises un attribut d'instance inutilement : c'est crade et cela limite l'utilisation de ta méthode (si j'ai des données généré autrement, je ne peux pas utiliser ta méthode pour ce calcul).
    • Tu dois baser le calcul moyenne sur les données que tu as, et non pas les générer aléatoirement.
      De plus il est préférable de compter les jours plutôt que de récupérer le nombre de jour d'un mois (c'est plus propre si tu as des données incomplètes).



    a++

  10. #70
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Voici ce que donne la méthode moyenne :

    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
     
    public Float moyenne(YearMonth month, Map<LocalDate, Float> temperatures) {
            SortedMap<LocalDate, Float> sMapTemperature;
            Collection<Float> vTemperatures;
            DateTimeField field = chrono.dayOfMonth(); // le champ permettant de récupérer le jour du mois                 
            Integer nbJoursMois = 0;
            Float somme = 0.f;
            Float moyenne;
            // 1. Récupérer les températures générées aléatoirement 
            sMapTemperature = genererTemperatures();
            // 1a. Récupérer les valeurs 
            vTemperatures = sMapTemperature.values();
            // 2. Créer un itérateur pour parcourir la collection de températures
            Iterator<Float> it = vTemperatures.iterator();
            // 3. Pour compter le nombre de jours dans le mois
            // 3a. Tant que je suis sur le mois et qu'un jour est présent dans le mois
            while (nbJoursMois < field.getMaximumValue(month) && it.hasNext()) {
                Float valeur = it.next();
                somme += valeur;
                ++nbJoursMois;
            }
            moyenne = somme / nbJoursMois;
            return moyenne;
        }

    Voici ce que donne la méthode genererMoyenneTemperaturesMois :
    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
     
    public Map<YearMonth, Float> genererMoyenneTemperaturesMois(Map<LocalDate, Float> map) {
            LocalDate firstDayOfNextMonth = new LocalDate(YEAR, 2, 2, chrono);
            YearMonth firstMonth = new YearMonth(YEAR, 1, chrono);
            Map<YearMonth, Float> hMapMoyTemperatures = new HashMap<>(12);
            Map<LocalDate, Float> mapTemperatures = new HashMap<>(31);
            // 1. Parcours sur les mois tant qu'on est sur la même année pour récupérer tous les mois
            for (YearMonth mois = firstMonth; mois.getYear() == YEAR; mois = mois.plusMonths(1)) {
                //1a. Parcours sur les jours tant que l'on est sur le même mois
                for (LocalDate jour = firstDay; jour.isBefore(firstDayOfNextMonth); jour = jour.plusDays(1)) {
                    Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
                    mapTemperatures.put(jour, temperatures);
                }
                // 2. Alimenter la Map avec le mois comme cle  et sa moyenne comme valeur 
                hMapMoyTemperatures.put(mois, moyenne(mois, mapTemperatures));
            }
            return hMapMoyTemperatures;
        }

    Sachant que je n'ai pas encore codé l'affichage

  11. #71
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    Tes deux premiers points dans la méthode moyenne(...) ne sont pas corrects ! Tu passes deux paramètres à ta méthode :
    1. month : le mois sur lequelle calculer la moyenne
    2. temperatures : la température pour chacun des jours

    et tu ne te sers pas la liste des températures car tu regénères automatiquement une autre liste de températures sur lequel tu fais la moyenne...
    C'est un peu si un prof, lorsqu'il calcule la moyenne de ses étudiants, au lieu de prendre les résultats des examens, lancait avec un dés de 20 les notes des élèves à chaque exams... bref, tu vois le problème.

    Bref, tu dois revoir ensuite ton parcours de boucle car il n'est plus adapter car il faut que tu filtre les jours du mois (il peut potentiellement y avoir des températures autres que celle du mois demandés);

    Pour résumer :
    1. TU OUBLIES LA GENERATION ALEATOIRE DES TEMPERATURES LORS DU CALCUL DE LA MOYENNE ! Sinon, tu risques de te faire taper par adiGuba (qui te le répette depuis plusieurs posts) et moi même

    2. tu ajoutes une méthode pour récuperer uniquement les températures du mois en demandé

  12. #72
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Voici le calcul de la moyenne. Par contre la condition dans le while est incorrecte ... mais je ne vois pas comment filtrer sur 1 mois
    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
     
    public Float moyenne(Map<LocalDate, Float> temperatures) {
            Collection<Float> vTemperatures;
            Float somme = 0.0f;
            Float moyenne;
     
            vTemperatures = temperatures.values();
            Iterator<Float> it = vTemperatures.iterator();
            // Tant que je suis sur le même mois, je dois filtrer les jours du mois 
            // pour calculer la moyenne des températures
            YearMonth mois = new YearMonth(chrono);
            LocalDate jour = new LocalDate(chrono);        
     
            while (mois.getMonthOfYear() < 12 && it.hasNext()) {
                Float valeur = it.next();
                somme += valeur;
     
            }
            moyenne = somme / jour.getDayOfMonth();
     
            return moyenne;
        }

  13. #73
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    La signature de la méthode moyenne était jusqu'à présent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Float moyenne(YearMonth month, Map<LocalDate, Float> temperatures)
    Tu l'as transformer pour retirer le mois sur lequelle il faut calculer la moyenne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Float moyenne(Map<LocalDate, Float> temperatures)
    donc il est normal que tu ais du mal à filtrer les dates sur le mois.... En simplifier, tu poses la question suivante : "peux tu me calculer la moyenne sur le mois suivant ? Je te donnes les températures, mais pour le mois, à toi de deviner celui que je veux ! Et fait en sorte que ce soit celui auquelle j'ai pensé ! mais comme t'es trop fort, je ne te donne pas le mois, ça serait trop simple"

    Donc deux solutions : soit t'es devin, soit tu ne peux pas calculer la moyenne pour un mois donnée sans connaitre le mois.

    et si tu as passé le mois d'une manière autre que par un paramètre de méthode... tu peux oublier !

    Citation Envoyé par transact Voir le message
    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
     
    public Float moyenne(Map<LocalDate, Float> temperatures) {
            Collection<Float> vTemperatures;
            Float somme = 0.0f; 
            Float moyenne;
     
            vTemperatures = temperatures.values();
            Iterator<Float> it = vTemperatures.iterator();
            // Tant que je suis sur le même mois, je dois filtrer les jours du mois 
            // pour calculer la moyenne des températures
            YearMonth mois = new YearMonth(chrono);
            LocalDate jour = new LocalDate(chrono);        
     
            while (mois.getMonthOfYear() < 12 && it.hasNext()) {
                Float valeur = it.next();
                somme += valeur;
     
            }
            moyenne = somme / jour.getDayOfMonth();
     
            return moyenne;
        }
    Pour ta boucle, tu dois parcourir l'ensemble des entrées de ton itérateur... rien ne dit que les données sont triés.
    Ensuite, c'est à l'intérieur de la boucle que tu dois filter avec un test sur le mois de la donnée. Mais tu vas avoir du mal, parce que dans ta boucle, tu as perdu une donnée importante : la date correspondant à la température !

  14. #74
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Bonsoir,

    Voici ce que donne la méthode pour calculer la moyenne
    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
     
    public Float moyenne(YearMonth mois, Map<LocalDate, Float> temperatures) {
            SortedMap<LocalDate, Float> vTemperatures = new TreeMap<>();
            Float somme = 0.0f;
            Float moyenne = 0.0f;
     
            vTemperatures.putAll(temperatures);
            Iterator<Map.Entry<LocalDate, Float>> it = vTemperatures.entrySet().iterator();
            // Tant que je suis sur le même mois, je dois filtrer les jours du mois 
            // pour calculer la moyenne des températures                              
            while (it.hasNext()) {
                Map.Entry<LocalDate, Float> entry = it.next();
                LocalDate date = entry.getKey();
                Float temperature = entry.getValue();
                // si la date de la température correspond au mois demandé 
                if (mois.getMonthOfYear() == date.get(DateTimeFieldType.monthOfYear())) {
                    // alors je fais la moyenne des températures
                    somme += temperature;
                    moyenne = somme / mois.getMonthOfYear();
                }
            }
     
            return moyenne;
        }

  15. #75
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    Peux tu m'expliquer pourquoi tu calcules la moyenne dans la boucle ?
    Au final, tu va calculer à chaque jour la moyenne, pour la recalculer pour le jour suivant... au final, seul le dernier calcul est utile. Sorts donc ça de la boucle.

    Au passage, comment fait tu pour tester le code que tu ecris ? Au vu des erreurs que tu postes, j'ai l'impression que tu as du mal à tester ton code.

  16. #76
    Membre confirmé Avatar de benratti
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    471
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2004
    Messages : 471
    Points : 649
    Points
    649
    Par défaut
    Quelques remarques sur ton code :

    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
    public Float moyenne(YearMonth mois, Map<LocalDate, Float> temperatures) {
            SortedMap<LocalDate, Float> vTemperatures = new TreeMap<>();
            Float somme = 0.0f;
            Float moyenne = 0.0f;
    
            vTemperatures.putAll(temperatures);  <= Pourquoi faire ça ?  ne peux tu pas travailler directement avec la Map passée en paramètre ?
            Iterator<Map.Entry<LocalDate, Float>> it = vTemperatures.entrySet().iterator();
            // Tant que je suis sur le même mois, je dois filtrer les jours du mois 
            // pour calculer la moyenne des températures                              
            while (it.hasNext()) {
                Map.Entry<LocalDate, Float> entry = it.next();
                LocalDate date = entry.getKey();
                Float temperature = entry.getValue();
                // si la date de la température correspond au mois demandé 
                if (mois.getMonthOfYear() == date.get(DateTimeFieldType.monthOfYear())) {
                    // alors je fais la moyenne des températures <= non tu es dans la boucle, attends d'avoir fini de calculer ta somme
                    somme += temperature;
                    moyenne = somme / mois.getMonthOfYear();
                }
            }
    
            return moyenne;
        }

    De plus il y a moyen de simplifier en utilisant une boucle for à la place d'un while et d'un iterator, et en plus ça permet d'eviter de chercher une condition de sortie de boucle !

    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
        public Float moyenne(YearMonth mois, Map<LocalDate, Float> temperatures) {
            Float somme = 0.0f;
            
            for( Map.Entry<LocalDate, Float> entry : temperatures.entrySet()) {
                LocalDate date = entry.getKey();
                Float temperature = entry.getValue();
                
                // si la date de la température correspond au mois demandé 
                if (mois.getMonthOfYear() == date.get(DateTimeFieldType.monthOfYear())) {
                    // alors je fais la moyenne des températures <= non tu es dans la boucle, attends d'avoir fini de calculer ta somme
                    somme += temperature;
                    
                }
            }
    
            return somme / mois.getMonthOfYear();

  17. #77
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    Merci pour ton retour, je n'ai pas testé le code puisque la boucle foreach pour l'affichage n'est pas encore implémenter vu que je dois modifier le comparateur pour afficher le mois le plus chaud.

    Tu me diras que même sans implémenter le comparator je pourrai au moins tester que la méthode moyenne retourne les bonnes données.

  18. #78
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par transact Voir le message
    Tu me diras que même sans implémenter le comparator je pourrai au moins tester que la méthode moyenne retourne les bonnes données.
    Oui car en l'état le code est toujours faux !
    La division par mois.getMonthOfYear() est complètement fausse : cela renvoi le mois en cours et non pas le nombre de jour du mois !
    Donc tu divises les 31 températures du mois d'aout par 8 et non pas 31 !!!



    Au passage j'aurais d'autres remarques à faire :
    • En local il est préférable de travailler sur des types primitifs. Surtout si on fait des calculs dans une boucle.
    • Plutôt que de diviser par le nombre de jour du mois, il est préférable de compter le nombre de valeur qu'on somme réellement afin d'éviter des résultats incohérents si la map en entrée n'est pas "complète" (en gérant le cas particulier 0 s'il n'y a aucune données pour un mois en particulier).
    • De même le fait de comparer simplement le mois peut être faux, puisque cela assume que la Map en entrée comporte uniquement les températures de l'année en cours.
      Il vaut mieux comparer année et mois si on veut un résultat cohérent quelque soit les données qu'on reçoit.

    Bref ca donnerait ceci :
    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 Float moyenne(YearMonth mois, Map<LocalDate, Float> temperatures) {
    	    float somme = 0.0f;
    	    int count = 0;
     
    	    for( Map.Entry<LocalDate, Float> entry : temperatures.entrySet()) {
    	        LocalDate date = entry.getKey();
    	        Float temperature = entry.getValue();
     
    	        if (temperature!=null && mois.getYear() == date.getYear() && mois.getMonthOfYear() == date.getMonthOfYear()) {
    	            somme += temperature;
    	            count++;
    	        }
    	    }
    	    if (count==0) {
    	    	return null;
    	    }
    	    return somme / count;
    	}



    Maintenant il y a un autre problème en ce qui me concerne : cette méthode calcule la moyenne pour un mois, et l'on utilise 12 fois dans genererMoyenneTemperaturesMois().
    Donc on parcours 12 fois les données de la Map


    Je pense qu'il serait plus logique de faire le calcul à la volée sur tous les mois, directement dans genererMoyenneTemperaturesMois().
    Par exemple pour rester dans ton cas où tu prend les températures de l'année défini dans la constante YEAR :
    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
    	public Map<YearMonth, Float> genererMoyenneTemperaturesMois(
    			Map<LocalDate, Float> temperatures) {
    		// 1. On crée des tableaux de 12 éléments pour stocker les valeurs de l'années
    		// (13 éléments car le 0 est ignoré - comme ca on ne s'embête pas à faire des -1/+1 partout)
    		float[] sum = new float[13];
    		int[] count = new int[13];
     
    		// On parcours toutes les données de la map :
    		for (Map.Entry<LocalDate, Float> entry : temperatures.entrySet()) {
    			LocalDate date = entry.getKey();
    			Float temperature = entry.getValue();
     
    			// Si la température est présente et que l'année correspond :
    			if (temperature != null && YEAR == date.getYear()) {
    				// On fait notre calcul dans le tableau correspondant :
    				int month = date.getMonthOfYear();
    				sum[month] += temperature;
    				count[month] += 1;
    			}
    		}
     
    		// On crée la Map résultat :
    		Map<YearMonth, Float> result = new HashMap<>(12);
    		for (int month = 1; month < 13; month++) {
    			// On calcule les valeurs finales :
    			YearMonth yearMonth = new YearMonth(YEAR, month);
    			if (count[month] > 0) {
    				// Et on ajoute dans la Map
    				result.put(yearMonth, sum[month] / count[month]);
    			}
     
    		}
    		return result;
    	}


    Au passage je revient sur ce choix de constante. C'est pas top car cela empêche de traiter d'autres années.
    Il aurait été préférable d'utiliser un paramètre supplémentaire à la place...



    a++

  19. #79
    Membre éprouvé
    Avatar de Rony Rauzduel
    Homme Profil pro
    En formation Architecte logiciel
    Inscrit en
    Décembre 2008
    Messages
    630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : En formation Architecte logiciel
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2008
    Messages : 630
    Points : 1 029
    Points
    1 029
    Par défaut
    De même le fait de comparer simplement le mois peut être faux, puisque cela assume que la Map en entrée comporte uniquement les températures de l'année en cours.
    Il vaut mieux comparer année et mois si on veut un résultat cohérent quelque soit les données qu'on reçoit.
    C'est exact et d'ailleurs même pertinent.

    Plutôt que de diviser par le nombre de jour du mois, il est préférable de compter le nombre de valeur qu'on somme réellement afin d'éviter des résultats incohérents si la map en entrée n'est pas "complète" (en gérant le cas particulier 0 s'il n'y a aucune données pour un mois en particulier).
    Il y a peu de chance que cela soit puisque les données sont générer aléatoirement par le seed placé dans le random... mais c'est un paramètre à verrouiller tout de même

    En local il est préférable de travailler sur des types primitifs. Surtout si on fait des calculs dans une boucle.
    Pour ma propre culture, en quoi cela est-il préférable?

    Au passage je revient sur ce choix de constante. C'est pas top car cela empêche de traiter d'autres années.
    Il aurait été préférable d'utiliser un paramètre supplémentaire à la place...
    Uniquement pour rester dans le cadre de l'exercice demandé

  20. #80
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par transact Voir le message
    Pour ma propre culture, en quoi cela est-il préférable?
    Le variables de types primitifs sont alloué sur la pile (= la mémoire alloué à la méthode).
    Les objets sont généralement alloué dans le tas (= la mémoire commune à tous le programme, géré par le GC), dont on garde une référence sur la pile.

    Mais à chaque modification de l'objet Float, tu crées en fait un nouvel objet dans le tas.
    Bref en clair tu donnes du boulot au GC pour pas grand chose.



    En réalité la JVM peut optimiser cela grace à l'escape analysis, et utiliser les Float comme des float, mais cela ne coûte pas plus cher de l'aider


    a++

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

Discussions similaires

  1. [Collections] map ordonnée + accès par indice
    Par jedimind dans le forum Collection et Stream
    Réponses: 8
    Dernier message: 11/11/2011, 12h43
  2. Réponses: 6
    Dernier message: 27/04/2011, 21h44
  3. [Entité-Association] Demande d'exercice pratique avancé pour conception d'ERD Merise
    Par patmaba dans le forum Schéma
    Réponses: 4
    Dernier message: 29/04/2009, 13h34
  4. Réponses: 4
    Dernier message: 07/02/2008, 12h34
  5. exercices "classe et collections" vb
    Par aabdel dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 30/05/2007, 18h36

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