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. #1
    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 Exercices pratiques, Random, Collection, Map
    Bonjour à tous,

    Actuellement je m'initie/perfectionne sur l'étude des containers (Collection/Map) en Java en faisant des exercices et je cherche quelques conseils concernant la méthodologie à adopter pour la résolution de ceux-ci.

    Enoncé : Générer un relevé de températures aléatoirement (comprises entre -10° et 40°) pour chaque jour de l'année 2014 et stocker dans une collection appropriée :
    On aura donc des couples (date,température).

    J'entrevoie brièvement ce qui faut utiliser, par exemple la classe java.lang.Random, la méthode Math.random() de la classe Math du package java.util.

    J'ai mis sur papier la formule mathématique de calcul permettant de générer le relevé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     min+(int)(Math.random()*(max+1-min))+min
    Quelle Map utiliser? SortedMap, HashMap ...

    Je ne suis pas novice en programmation Java ... mais ce que je recherche avant tout est une méthode pour résoudre une problématique.

    Comment procéder ?

    Merci d'avance pour vos conseils.

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Ben il faut quelques réflexes de POO à acquerir.

    La manière dont tu génère l'aléatoire, finalement, ça importe peu dans la question tu fais ce que tu veux. La question se pose du stockage. Que dois tu stocker?

    Une valeur, associé à une date, et vraisemblablement accédé par date. Décompose le problème:

    une valeur:
    • Float
    • Integer
    • classe personnelle "Temperature"
    • autre idée?



    une date:
    • java.util.Date
    • String
    • java.util.Calendar
    • java.time.LocalDate (java 8)


    associé:
    • Map
    • SortedMap
    • Quelle implémentation?


    Une bonne manière de stocker la température, selon moi, c'est Float, L'integer n'est pas assez précis, une classe custom n'est pas facilement justifiable, et je n'ai pas d'autre idée
    pour la date, java.util.Date est compliqué à manipuler et contient aussi des heures, Calendar rajoute en plus une timezone. String a l'inconvénient de te lier à une représentation de la date. Finalement LocalDate semble avoir tous les avantages: indépendant de l'heure et de la timezone, facile à manipuler, pas trop contraint.

    Ce qui nous amènes avec les deux choix faciles:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Map<LocalDate,Float>
    SortedMap<LocalDate,Float>
    triée ou pas triée la map? La maintenir triée, ça a un coût, tant en terme de mémoire que de temps CPU. As-tu besoin de parcourir les dates dans l'ordre? Il y a fort à parier que tu voudra afficher un tableau trié de mesure. Donc le SortedMap se justifie probablement. Pour l'implémentation, plus qu'à faire ton choix dans ce qui est proposé, et il n'y a que TreeMap de vraiment disponible. On sent bien à lire le nom de "ConcurrentSkipListMap" que ça ne colle pas trop au besoin

  3. #3
    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
    Dans un premier temps merci pour tes conseils avisés tchize_.
    Les concepts de POO s'acquièrent en pratiquant ce genre d'exercice, et c'est le pourquoi de ma pratique.
    J'utilise Java 7 donc je devrai me passer de LocalDate, je pensai utiliser GregorianCalendar ou JodaTime qu'en penses-tu?

  4. #4
    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
    GregorianCalendar est un peu lourd en mémoire et en temps de calcul. Dans ton cas très précis ce n'est pas à proprement parler un problème, mais dans le cas général tu ne voudrais jamais indexer une Map avec des GregorianCalendar. Il y a aussi le fait que c'est une classe mutable et faite pour être mutée, ce qu'il faut éviter de mettre comme clés dans des Map, car le mécanisme de Map ne fonctionne plus si on modifie les clés qu'elle contient après les avoir insérées.

    Joda-Time est très bien, mais c'est une bibliothèque tierce, que tu vas devoir ajouter. Et puis il va donc falloir décider quelle classe tu utilises dans ta Map. (Oui, bon, laquelle prendre est évident, mais c'est là l'exercice, hein.)
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    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
    Ola!Ola! ... j'ai déjà "du mal" à agréger toutes ses informations pour résoudre cet exercice.
    Entendu pour GregorianCalendar et c'est noté dans le cadre professionnel mais pour cet exercice aucune mutation ne sera effectuée donc je partirai sur du GregorianCalendar.
    Merci pour cette information.

  6. #6
    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 début de mon code mais je planche sur le reste
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public final class Temperature {
        private final static int YEAR = 2014;
        public static void main(String[] args) {        
            SortedMap<GregorianCalendar, Float> tMapTemperatures = new TreeMap<>();
            Calendar dates = new GregorianCalendar(YEAR, Calendar.MONTH, Calendar.DAY_OF_WEEK);
            DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
     
        }    
    }

  7. #7
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    heu pas tout à fait. C'est


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Calendar january1st = new GregorianCalendar(YEAR, Calendar.JANUARY, 1);
    Calendar noel= new GregorianCalendar(YEAR, Calendar.DECEMBER, 25);

  8. #8
    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
    Oups! en faite ce que je comprends selon la documentation Java il faut remplir le calendrier au préalable à l'aide de la méthode
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    add(int field, int value)
    En continuant mon implémentation je me suis aperçu qu'il était préférable de créer une classe Calendrier qui contiendra la méthode suivante :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class Calendrier {
     
        private static Calendar calendar = new GregorianCalendar();
     
        public static Calendar getCalendrier() {
            calendar.clear();
            calendar.add(Calendar.YEAR, 2014);
            calendar.add(Calendar.MONTH, 0); // Janvier
            etc ...
            return calendar;
    D'ailleurs le test suivant
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    calendar.set(Calendar.YEAR, 2014);
    calendar.set(Calendar.MONTH, 9);
    calendar.set(Calendar.DAY_OF_MONTH, 2);
    et dans mon main
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    System.out.println(df.format(Calendrier.getCalendrier().getTime()));
    m'affiche dans la console 02/10/2014

  9. #9
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Avec ton code, tout le monde va partager le même calendrier qui aura comme valeur celle initialisée au dernier appel getCalendrier. Ce n'est pas un bon plan. Pourquoi la méthode que tu avais entamée avec le contructeur ne te convient pas?

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

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

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par tchize_ Voir le message
    Avec ton code, tout le monde va partager le même calendrier qui aura comme valeur celle initialisée au dernier appel getCalendrier. Ce n'est pas un bon plan. Pourquoi la méthode que tu avais entamée avec le contructeur ne te convient pas?
    Gros +1 !


    Citation Envoyé par transact Voir le message
    Entendu pour GregorianCalendar et c'est noté dans le cadre professionnel mais pour cet exercice aucune mutation ne sera effectuée donc je partirai sur du GregorianCalendar.
    Et paf ! T'es tombé dans le piège.
    Tu annonçais fièrement ne faire aucune mutation sur les GregorianCalendar, mais c'est pile poil ce que tu fais avec ta méthode getCalendrier() : tu retournes une unique instance partagé par tout le monde.
    Du coup toutes les variables obtenu via cette méthode seront toujours égales à la dernière valeur indiqué.



    Lorsqu'on veut utiliser un objet en clef d'une Map, il est impératif d'utiliser un objet immuable.
    Se contenter de dire "je ne vais pas le modifier" ne suffit pas, car l'erreur de manip surviendra toujours et cela engendrera des bugs incompréhensibles !!!


    Si tu ne peux vraiment pas utiliser Java 8 ou Joda-Time, le plus simple serait de se créer une classe "Date" immuable...
    Pour un usage basique c'est pas bien méchant à faire :
    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
    59
    60
    /**
     * Date GMT (year-month-day)
     */
    public final class MyDate implements Comparable<MyDate> {
     
    	private static final TimeZone GMT = TimeZone.getTimeZone("GMT");
     
    	private final long timestamp;
     
    	private MyDate(long timestamp) {
    		this.timestamp = timestamp;
    	}
     
    	public static MyDate of(int year, int month, int day) {
    		try {
    			// Contrairement à son nom getInstance() crée une nouvelle instance :
    			Calendar cal = Calendar.getInstance(GMT);
    			// On défini la date (à 12:00) :
    			cal.clear();
    			cal.set(Calendar.HOUR_OF_DAY, 12);
    			cal.set(Calendar.YEAR, year);
    			cal.set(Calendar.MONTH, month-1);
    			cal.set(Calendar.DAY_OF_MONTH, day);
     
    			// On désactive le mode Lenient
    			// (pour générer une erreur si la date est fausse)
    			cal.setLenient(false);
     
    			return new MyDate(cal.getTimeInMillis());
    		} catch (Exception e) {
    			throw new IllegalArgumentException(String.format("%04d-%02d-%02d", year, month, day), e);
    		}
    	}
     
    	@Override
    	public int compareTo(MyDate o) {
    		return Long.compare(this.timestamp, o.timestamp);
    	}
     
    	@Override
    	public boolean equals(Object obj) {
    		if (obj==this) return true;
    		if (obj instanceof MyDate) {
    			return this.timestamp == ((MyDate)obj).timestamp;
    		}
    		return false;
    	}
     
    	@Override
    	public int hashCode() {
    		// basé sur le hashCode() de Long :
    		return (int)(this.timestamp ^ (this.timestamp >>> 32));
    	}
     
    	public String toString() {
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    		sdf.setTimeZone(GMT);
    		return sdf.format(this.timestamp);
    	}
    }
    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	MyDate january1st = MyDate.of(YEAR, 1, 1);
    	MyDate noel = MyDate.of(YEAR, 12, 25);
     
    	MyDate badDate = MyDate.of(YEAR, 2, 30); // IllegalArgumentException

    Maintenant JodaTime (ou LocalDate de JAva 8) serait bien plus adéquate car bien plus fonctionnelle !


    a++

  11. #11
    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
    Ton problème m'a donné envie de le développer en utilisant au maximum les nouveautés java 8 : lambda, stream, java.time.*

    Ca donne ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
           int year = 2014;
           LocalDate firstDay = LocalDate.of(year, JANUARY, 1);
     
           int max = 40;
           int min = -10;
     
           Random random = new Random((new Date()).getTime());
     
           SortedMap<LocalDate, Float> map = Stream
     
                    // j'indique comment récupérer tous les jours depuis le 1er janvier 2014
                    .iterate(firstDay, day -> day.plus(1, ChronoUnit.DAYS))            
     
                    // je limite le nombre de jour à ceux de 2014, c'est à dire 365 
                    .limit(firstDay.lengthOfYear())                                                     
     
                    // je genere ma map à partir du stream des jours de l'année
                    .reduce(                                                                                    
                            Maps.newTreeMap(),  // j'utilise guava, mais un new TreeMap<LocalDate,Float>() peut faire l'affaire
                            (SortedMap<LocalDate, Float> map1, LocalDate day) -> {
     
                                // je genere une température, la mulitplication par deux permet simplement d'avoir une echelle de 1/2 degree entre -10° et 40°, 
                                // le +1 permet de générer 40°
                                float temperature = (random.nextInt(2 * (max - min)) + 1 + 2 * min) / 2f;
     
                                // j'ajoute dans ma map
                                map1.put(day, temperature);
                                return map1;
                            },
                            // ca ne sert à pas grand chose car je n'utilise pas de stream parallele, donc la combinaison du reduce n'ai pas utilisé. 
                            (map1, map2) -> {
                                map1.putAll(map2);
                                return map1;
                            }
                    );

  12. #12
    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 benratti Voir le message
    Ton problème m'a donné envie de le développer en utilisant au maximum les nouveautés java 8 : lambda, stream, java.time.*
    Ton code fonctionne mais sur le principe il est faux car tu utilises mal reduce().


    En effet le paramètre identity de reduce() ne devrait pas être modifié, et devrait plutôt correspondre à un constante représentant la valeur initiale.
    L'objectif de reduce() n'est pas d’emmagasiner les valeurs, mais plutôt de réduire le résultat à un seul élément... et 'identity' sert de valeur par défaut...

    D'ailleurs tu n'as pas tester en parallèle... mais cela plante lamentablement car tous les threads utilisent alors la même Map (et TreeMap n'est pas thread-safe)



    En fait reduce() c'est bien pour des sommes ou des min/max...
    Mais pour emmagasiner des valeurs, il faut plutôt utiliser collect() :
    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
            SortedMap<LocalDate, Float> map = Stream
     
                    // j'indique comment récupérer tous les jours depuis le 1er janvier 2014
                    .iterate(firstDay, day -> day.plus(1, ChronoUnit.DAYS))            
     
                    // je limite le nombre de jour à ceux de 2014, c'est à dire 365 
                    .limit(firstDay.lengthOfYear())
     
                    // On emmagasine les valeurs dans un collecteur :
                    .collect(
                            // "Supplier" qui fourni une instance du collecteur
                            // (il peut y en avoir plusieurs si on est en parallèle)
                            TreeMap::new,
     
                            // "Accumulator" qui permet d'accumuler un élément dans le collecteur
                            (treemap,date) -> {
                                float temperature = (random.nextInt(2 * (max - min)) + 1 + 2 * min) / 2f;
                                treemap.put(date, temperature);
                            },
     
                            // "Combiner" qui permet de regrouper plusieurs collecteur (exécution en parallèle)
                            Map::putAll
                    );
    Et là cela marchera bien même en parallèle !



    A noter l'existence de la classe Collectors qui fournit un ensemble de collector aux fonctionnalités simplifiés.
    Par exemple dans notre cas pour créer une TreeMap on pourrait faire 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
            SortedMap<LocalDate, Float> map = Stream
     
                    // j'indique comment récupérer tous les jours depuis le 1er janvier 2014
                    .iterate(firstDay, day -> day.plus(1, ChronoUnit.DAYS))            
     
                    // je limite le nombre de jour à ceux de 2014, c'est à dire 365 
                    .limit(firstDay.lengthOfYear())
     
                    .collect(Collectors.toMap(
                            // Fonction générant la clef d'une date :
                            date -> date,   // ou Function.identity()
                            // Fonction générant la valeur d'une date :
                            date -> (random.nextInt(2 * (max - min)) + 1 + 2 * min) / 2f,
                            // Fonction permettant de regrouper des valeurs multiples pour une même clef
                            // (ici on veut interdire cela)
                            (f1,f2)->{throw new IllegalStateException("duplicate key");},
                            // Supplier fournissant une instance du collecteur :
                            TreeMap::new));


    Sinon c'est un petit détail mais c'est bien de définir des constantes même au sein d'une méthode en utilisant final avec des littéraux (int/double/String...) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
           final int max = 40;
           final int min = -10;
    D'une part cela évite des modifications par erreurs de ces valeurs, mais cela permet également au compilateur de faire certains calcul à l'avance...


    a++

  13. #13
    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
    Citation Envoyé par adiGuba Voir le message
    Ton code fonctionne mais sur le principe il est faux car tu utilises mal reduce().


    En effet le paramètre identity de reduce() ne devrait pas être modifié, et devrait plutôt correspondre à un constante représentant la valeur initiale.
    L'objectif de reduce() n'est pas d’emmagasiner les valeurs, mais plutôt de réduire le résultat à un seul élément... et 'identity' sert de valeur par défaut...
    merci pour l'explication. J'avais bien vu le collect() mais pas bien compris le fonctionnement.

    Citation Envoyé par adiGuba Voir le message
    D'ailleurs tu n'as pas tester en parallèle... mais cela plante lamentablement car tous les threads utilisent alors la même Map (et TreeMap n'est pas thread-safe)
    J'avais bien vu le problème, mais l'avait mal réglé en utilisant des concurrentMap, ce qui plombait les perfs au passage (de 5 ms à 125 ms en moyenne sur mon ordi). Effectivement, c’était du à une mauvaise compréhension du fonctionnement des streams, et surtout des methodes reduce() et collect()

    Citation Envoyé par adiGuba Voir le message
    En fait reduce() c'est bien pour des sommes ou des min/max...
    Mais pour emmagasiner des valeurs, il faut plutôt utiliser collect() :

    Et là cela marchera bien même en parallèle !
    ok, c'est compris maintenant !

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

    Merci pour vos retours cela me fait vraiment plaisir.
    De mon côté j'ai mis en place ce squelette de conception, je voudrai que vous me disiez ce que vous en pensez
    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
     
    public class TestTemperature {
     
        private SortedMap<DateTime, Float> tMapTemperatures = new TreeMap<>();
        private DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        private DateTime dt = new DateTime(2014, 1, 1, 0, 0, GregorianChronology.getInstance());
        private Random rand = new Random();
     
        // Méthode permettant de construire le calendrier pour l'année 2014
        public void genererCalendrier() {
            // traitements
        }
     
        // Méthode permettant de générer aléatoirement les températures
        public void genererTemperature() {
            // traitements
        }
     
        // Méthode permettant de générer le relevé de températures
        public void genererReleveTemperatures() {
            // traitements
        }
        // Dans le main invocation des méthodes 
        public static void main(String[] args) {
     
        }
    }

    Merci d'avance.
    Transact.

  15. #15
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Pourquoi un DateTime plutot qu'un LocalDate, vu tes que tes entrées sont journalières?

  16. #16
    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
    Autant pour moi entre 2 postes j'ai modifié mon code
    Ceci est mieux
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    private LocalDate firstDay = new LocalDate(YEAR, Calendar.JANUARY, 1, GregorianChronology.getInstance());

    Ensuite je pense qu'il est préférable de réduire le code ainsi :
    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 class TestTemperature {
     
        private final static int MAX = 40;
        private final static int MIN = -10;
        private final static int YEAR = 2014;
        private LocalDate firstDay = new LocalDate(YEAR, Calendar.JANUARY, 1, GregorianChronology.getInstance());
        private SortedMap<LocalDate, Float> tMapTemperatures = new TreeMap<>();
     
        private Random rand = new Random(new java.util.Date().getTime());
     
        // Méthode permettant de générer le relevé de températures
        public SortedMap<LocalDate, Float> genererReleveTemperatures() {
            // Récupérer tous les jours depuis le 1er janvier 2014
            return tMapTemperatures;
        }
     
        // Dans le main invocation des méthodes 
        public static void main(String[] args) {
     
        }
    }

  17. #17
    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 mon code finalisé ... et qui compile sans erreur, mais par contre je ne parviens pas à afficher les valeurs avec une boucle parce queTreeMap n'implémente pas Iterator donc comment procéder?
    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
     
    public class TestTemperature {
     
        private final static int MAX = 40;
        private final static int MIN = -10;
        private final static int YEAR = 2014;
        private final static Chronology chrono = GregorianChronology.getInstance();
        private static LocalDate firstDay = new LocalDate(YEAR, 1, 1, chrono);
        private static Random rand = new Random(new java.util.Date().getTime());
     
        // Méthode permettant de générer aléatoirement le relevé de températures journalier pour l'année 2014
        public static SortedMap<LocalDate, Float> genererReleveTemperatures() {
            SortedMap<LocalDate, Float> tMapTemperatures = new TreeMap<>();
            // Récupérer tous les jours de l'annéee 2014 depuis le 1er janvier 
            LocalDate jour = firstDay.plusDays(364);
            // S'occuper de récupérer les températures 
            Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
            // Alimenter la TreeMap
            tMapTemperatures.put(jour, temperatures);        
            return tMapTemperatures;
        }
     
        // Dans le main invocation des méthodes 
        public static void main(String[] args) {
            TestTemperature.genererReleveTemperatures();
        }
    }

  18. #18
    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
    Oups, je suis désolé, il s'agit d'une Map donc elle implémente l'interface Map.Entry<K,V> et il faut utiliser la méthode entrySet() pour afficher les clés et leur valeur.

  19. #19
    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
    Par contre en exécutant le code il ne m'affiche qu'un seul enregistrement celui du 31/12/2014 et pas les 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    public class TestTemperature {
     
        private final static int MAX = 40;
        private final static int MIN = -10;
        private final static int YEAR = 2014;
        private static DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
        private final static Chronology chrono = GregorianChronology.getInstance();
        private static LocalDate firstDay = new LocalDate(YEAR, 1, 1, chrono);
        private static Random rand = new Random(new java.util.Date().getTime());
     
        // Méthode permettant de générer aléatoirement le relevé de températures journalier pour l'année 2014
        public static SortedMap<LocalDate, Float> genererReleveTemperatures() {
            SortedMap<LocalDate, Float> tMapTemperatures = new TreeMap<>();
            // Récupérer tous les jours de l'annéee 2014 depuis le 1er janvier 
            LocalDate jour = firstDay.plusDays(364);
            // S'occuper de récupérer les températures 
            Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
            // Alimenter la TreeMap
            tMapTemperatures.put(jour, temperatures);
            for (Map.Entry<LocalDate, Float> entry : tMapTemperatures.entrySet()) { 
                LocalDate localDate = entry.getKey();
                Float float1 = entry.getValue();
                System.out.println(localDate + " : " + float1 + " °C");
            }
            return tMapTemperatures;
        }
     
        // Dans le main invocation de la méthode
        public static void main(String[] args) {
            TestTemperature.genererReleveTemperatures();
        }
    }

  20. #20
    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 benratti Voir le message
    merci pour l'explication. J'avais bien vu le collect() mais pas bien compris le fonctionnement.
    Il faut dire que reduce() est trompeur et semble faire l'affaire (et cela peut le faire tant qu'on reste en séquentiel, même si ce n'est pas dans l'esprit).

    Le truc c'est que reduce() c'est pour pour faire des opérations de base (average, sum, min, max, et count)... mais il y a déjà des fonctions toutes faites pour cela !



    Citation Envoyé par transact Voir le message
    Par contre en exécutant le code il ne m'affiche qu'un seul enregistrement celui du 31/12/2014 et pas les autres
    Ben contrairement à ton commentaire, tu ne parcours pas tous les jours de l'année mais tu te contentes d'ajouter 364 jour... et d'ajouter uniquement ce jour là dans la Map :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     // Récupérer tous les jours de l'annéee 2014 depuis le 1er janvier 
            LocalDate jour = firstDay.plusDays(364);
            // S'occuper de récupérer les températures 
            Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
            // Alimenter la TreeMap
     
            tMapTemperatures.put(jour, temperatures);
    Il n'y a pas de boucle et un seul put(), donc un seul élément dans la Map !


    Bref il te faut boucler sur tous les jours de l'année :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            // Parcours sur les dates, tant qu'on est sur la même année
            for (LocalDate jour = firstDay; jour.getYear()==YEAR; jour=jour.plusDays(1)) {
                Float temperatures = (rand.nextInt(2 * (MAX - MIN)) + 1 + 2 * MIN) / 2f;
                tMapTemperatures.put(jour, temperatures);
            }
    a++

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 5 12345 DernièreDernière

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