Question

C'est méchant pour moi...Je suis un gars PHP travaillant en Java sur un projet JSP.Je sais comment faire ce que je tente avec trop de code et un manque total de finesse.

Je préférerais le faire correctement.Voici la situation :

J'écris un petit affichage pour montrer aux clients quels jours ils peuvent arroser leur pelouse en fonction de leur groupe d'arrosage (ABCDE) et à quelle période de l'année il s'agit.Nos saisons ressemblent à ceci :Été (5-1 à 8-31) printemps (3-1 à 4-30) automne (9-1 à 10-31) hiver (11-1 à 2-28)

Un exemple pourrait être :

Si je suis dans le groupe A, voici mes horaires autorisés :Hiver:Mondays seulement printemps:Mardi, jeudi, Samed Summer:Tout jour tombe:mardi, jeudi, samedi

Si j'écrivais ceci en PHP, j'utiliserais des tableaux comme celui-ci :

//M=Monday,t=Tuesday,T=Thursday.... etc
$schedule["A"]["Winter"]='M';
$schedule["A"]["Spring"]='tTS';
$schedule["A"]["Summer"]='Any';
$schedule["A"]["Fall"]='tTS';
$schedule["B"]["Winter"]='t';

Je POURRAIS créer les tableaux des jours (array("Tuesday","Thursday","Saturday")) etc, mais ce n'est pas nécessaire pour ce que j'essaie vraiment d'accomplir.

Je devrai également configurer des tableaux pour déterminer à quelle saison je me trouve :

$seasons["Summer"]["start"]=0501;
$seasons["Summer"]["end"]=0801;

Quelqu'un peut-il suggérer une façon vraiment cool de procéder ?J'aurai la date d'aujourd'hui et la lettre du groupe.Je devrai quitter ma fonction un jour (M) ou une série de jours (tTS), (Any).

Était-ce utile?

La solution

Vous pouvez faire essentiellement le même code avec Hashtables (ou une autre carte) :

Hashtable<String, Hashtable<String, String>> schedule
    = new Hashtable<String, Hashtable<String, String>>();
schedule.put("A", new Hashtable<String, String>());
schedule.put("B", new Hashtable<String, String>());
schedule.put("C", new Hashtable<String, String>());
schedule.put("D", new Hashtable<String, String>());
schedule.put("E", new Hashtable<String, String>());

schedule.get("A").put("Winter", "M");
schedule.get("A").put("Spring", "tTS");
// Etc...

Pas aussi élégant, mais là encore, Java n'est pas un langage dynamique et il n'a pas de hachage au niveau du langage.

Note:Vous pourrez peut-être trouver une meilleure solution, cela m'est venu à l'esprit en lisant votre question.

Autres conseils

N'essayez pas d'être aussi dynamique que PHP.Tu pourrais essayer d'abord définir De quoi as-tu besoin.

interface Season
{
    public string getDays();
}

interface User
{
    public Season getWinter();
    public Season getSpring();
    public Season getSummer();
    public Season getFall();
}

interface UserMap
{
    public User getUser(string name);
}

Et s'il vous plaît, lisez la documentation de Table de hachage avant de l'utiliser.Cette classe est synchronisée, ce qui signifie que chaque appel est protégé contre le multithreading, ce qui ralentit vraiment l'accès lorsque vous n'avez pas besoin de protection supplémentaire.Veuillez utiliser n'importe quel Carte mise en œuvre à la place comme Carte de hachage ou ArbreCarte.

Il semble que tout le monde essaie de trouver la manière Java de le faire comme vous le faites en PHP, au lieu de la manière dont cela devrait être fait en Java.Considérez simplement chaque élément de votre tableau comme un objet ou, à tout le moins, le premier niveau du tableau comme un objet et chaque sous-niveau comme des variables à l'intérieur de l'objet.Créez une structure de données que vous remplissez avec lesdits objets et accédez aux objets via les accesseurs donnés à la structure de données.

Quelque chose comme:

class Schedule
{
  private String group;
  private String season;
  private String rundays;
  public Schedule() { this.group = null; this.season = null; this.rundays= null; }
  public void setGroup(String g) { this.group = g; }
  public String getGroup() { return this.group; }
  ...
}

public ArrayList<Schedule> schedules = new ArrayList<Schedule>();
Schedule s = new Schedule();
s.setGroup(...);
...
schedules.add(s);
...

Bien sûr, ce n’est probablement pas vrai non plus.Je ferais de chaque saison un objet, et peut-être de chaque liste de jours de la semaine aussi.Quoi qu'il en soit, c'est plus facilement réutilisé, compris et extensible qu'une table de hachage entravée qui tente d'imiter votre code PHP.Bien sûr, PHP a également des objets, et vous devez les utiliser de la même manière au lieu de vos uber-arrays, dans la mesure du possible.Je comprends cependant la tentation de tricher.PHP rend les choses si simples et si amusantes !

Voici une façon de procéder pourrait à quoi ressemble, vous pouvez comprendre le reste :

A = new Group();
A.getSeason(Seasons.WINTER).addDay(Days.MONDAY);
A.getSeason(Seasons.SPRING).addDay(Days.TUESDAY).addDay(Days.THURSDAY);
A.getSeason(Seasons.SPRING).addDays(Days.MONDAY, Days.TUESDAY, ...);

schedule = new Schedule();
schedule.addWateringGroup( A );

Je ne suis pas un programmeur Java, mais m'éloigner de Java et penser simplement en termes plus indépendants du langage - une façon plus propre de le faire pourrait être d'utiliser soit des constantes, soit des types énumérés.Cela devrait fonctionner dans n'importe quel langage prenant en charge les tableaux multidimensionnels.

Si vous utilisez des constantes nommées, où, par exemple :

int A = 0;
int B = 1;
int C = 2;
int D = 3;

int Spring = 0; 
int Summer = 1;
int Winter = 2; 
int Fall = 3;
...

Ensuite, les constantes servent d'indices de tableau plus lisibles :

schedule[A][Winter]="M";
schedule[A][Spring]="tTS";
schedule[A][Summer]="Any";
schedule[A][Fall]="tTS";
schedule[B][Winter]="t";

Utilisation de types énumérés :

enum groups
{
  A = 0,
  B = 1,
  C = 2,
  D = 3
}

enum seasons
{
  Spring = 0,
  Summer = 1,
  Fall = 2,
  Winter = 3
}
...
schedule[groups.A][seasons.Winter]="M";
schedule[groups.A][seasons.Spring]="tTS";
schedule[groups.A][seasons.Summer]="Any";
schedule[groups.A][seasons.Fall]="tTS";
schedule[groups.B][seasons.Winter]="t";

Je ne comprends absolument pas pourquoi certains d'entre vous semblent penser que lancer des tas d'objets sur le code est la voie à suivre.Par exemple, il y a exactement quatre saisons, et ce n'est pas le cas. faire ou magasin rien.Comment simplifier quelque chose pour en faire des objets ?Wing a tout à fait raison de dire que ceux-ci devraient probablement être constantes (ou peut-être des énumérations).

Ce dont Bruce a besoin, au fond, c'est simplement une table de recherche.Il n'a pas besoin d'une hiérarchie d'objets et d'interfaces ;il a besoin d'un moyen de rechercher un planning basé sur une saison et un identifiant de groupe.Transformer des choses en objets n’a de sens que si elles ont des responsabilités ou un état.S'ils n'ont ni l'un ni l'autre, alors ce sont simplement des identifiants, et la création d'objets spéciaux pour eux ne fait qu'agrandir la base de code.

Toi pourrait construire, par exemple, Group objets qui contiennent chacun un ensemble de chaînes de planification (une pour chaque saison), mais si tous les Group l'objet fournit une fonctionnalité de recherche, alors vous avez réinventé la table de recherche d'une manière beaucoup moins intuitive.S'il doit rechercher le groupe, puis rechercher le calendrier, tout ce qu'il a est une table de recherche en deux étapes qui a pris plus de temps à coder, est plus susceptible d'être boguée et sera plus difficile à maintenir.

Je suis avec ceux qui suggèrent d'encapsuler la fonction dans les objets.

import java.util.Date;
import java.util.Map;
import java.util.Set;

public class Group {

    private String groupName;

    private Map<Season, Set<Day>> schedule;

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public Map<Season, Set<Day>> getSchedule() {
        return schedule;
    }

    public void setSchedule(Map<Season, Set<Day>> schedule) {
        this.schedule = schedule;
    }

    public String getScheduleFor(Date date) {
        Season now = Season.getSeason(date);
        Set<Day> days = schedule.get(now);
        return Day.getDaysForDisplay(days);
    }

}

MODIFIER:De plus, vos plages de dates ne prennent pas en compte les années bissextiles :

Nos saisons ressemblent à ceci :Été (5-1 à 8-31) printemps (3-1 à 4-30) automne (9-1 à 10-31) hiver (11-1 à 2-28)

Je suis d'accord que vous devriez absolument mettre cette logique derrière l'interface claire de :

public String lookupDays(String group, String date);

mais peut-être devriez-vous coller les données dans un fichier de propriétés.Je ne suis pas contre le codage en dur de ces données dans vos fichiers sources mais, comme vous l'avez remarqué, Java peut être assez verbeux lorsqu'il s'agit de collections imbriquées.Votre fichier pourrait ressembler à :

A. Été = M
A. Printemps = tTS
B. Été = T

Habituellement, je n'aime pas déplacer des données statiques comme celle-ci vers un fichier externe car cela augmente la "distance" entre les données et le code qui les utilise.Cependant, chaque fois que vous avez affaire à des collections imbriquées, en particulier des cartes, les choses peuvent devenir très laides, très rapidement.

Si vous n'aimez pas cette idée, vous pouvez peut-être faire quelque chose comme ceci :

public class WaterScheduler
{
  private static final Map<String, String> GROUP2SEASON = new HashMap<String, String>();
  static
  {
    addEntry("A", "Summer", "M");
    addEntry("A", "Spring", "tTS");
    addEntry("B", "Summer", "T");
  }

  private static void addEntry(String group, String season, String value)
  {
    GROUP2SEASON.put(group + "." + season, value);
  }

}

Vous perdez un peu en lisibilité, mais au moins les données sont plus proches de l'endroit où elles vont être utilisées.

La « date » doit-elle être un paramètre ?Si vous affichez simplement le programme d'arrosage actuel, la classe WateringSchedule elle-même peut déterminer le jour et donc la saison.Ensuite, ayez simplement une méthode qui renvoie une carte où la clé est la lettre du groupe.Quelque chose comme:

public Map<String,List<String>> getGroupToScheduledDaysMap() {
  // instantiate a date or whatever to decide what Map to return
}

Puis dans la page JSP

<c:forEach var="day" items="${scheduler.groupToScheduledDaysMap["A"]}">
   ${day}
</c:forEach>

Si vous devez afficher les horaires de plusieurs saisons, vous devez disposer d'une méthode dans la classe WateringSchedule qui renvoie une carte où les saisons sont les clés, puis les cartes de groupToScheduledDays sont les valeurs.

Une meilleure solution serait peut-être de mettre toutes ces données dans une base de données, au lieu de les coder en dur dans vos sources ou d'utiliser des fichiers de propriétés.

L'utilisation d'une base de données sera beaucoup plus facile à maintenir, et il existe un variété de gratuit base de données moteurs à choisir.

Deux de ces moteurs de base de données sont entièrement implémentés en Java et peuvent être intégrés dans une application simplement en incluant un fichier jar.C'est un peu lourd, bien sûr, mais c'est beaucoup plus évolutif et plus facile à entretenir.Ce n'est pas parce qu'il y a 20 enregistrements aujourd'hui qu'il n'y en aura pas plus plus tard en raison de l'évolution des exigences ou de l'évolution des fonctionnalités.

Si, dans quelques semaines ou quelques mois, vous décidez d'ajouter, par exemple, des restrictions d'arrosage en fonction de l'heure de la journée, il sera beaucoup plus facile d'ajouter cette fonctionnalité si vous utilisez déjà une base de données.Même si cela n'arrive jamais, vous avez passé quelques heures à apprendre à intégrer une base de données dans une application.

Il n’y a pas de jolie solution.Java ne fait tout simplement pas bien ce genre de choses.La solution de Mike est à peu près la façon de procéder si vous voulez des chaînes comme indices (clés).Une autre option si la configuration du hachage des hachages est trop moche est d'ajouter les chaînes ensemble (volées sans vergogne à Mike et modifiées) :

Hashtable<String, String> schedule = new Hashtable<String, String>();
schedule.put("A-Winter", "M");
schedule.put("A-Spring", "tTS");

puis recherchez:

String val = schedule.get(group + "-" + season);

Si vous n'êtes pas satisfait de la laideur générale (et je ne vous en veux pas), mettez tout cela derrière un appel de méthode :

String whenCanIWater(String group, Date date) { /* ugliness here */ }

tl;dr

À l'aide des fonctionnalités et des classes du langage Java moderne, définissez vos propres énumérations pour représenter les saisons et les groupes.

Schedule.daysForGroupOnDate( 
    Group.D , 
    LocalDate.now()
)  

Cette méthode donne un Set de DayOfWeek enum objets (pas du simple texte !), tels que DayOfWeek.TUESDAY & DayOfWeek.THURSDAY.

Java moderne

Quelqu'un peut-il suggérer une façon vraiment cool de procéder ?

Oui.

Java moderne possède des classes, des collections et des énumérations intégrées pour vous aider à résoudre ce problème.

Le java.time Le framework intégré à Java offre le Month énumération et DayOfWeek énumération.

Le EnumSet et EnumMap fournir des implémentations de Set et Map qui sont optimisés pour une utilisation avec des énumérations pour une exécution rapide dans très peu de mémoire.

Vous pouvez définir le vôtre énumérations pour représenter votre saison et vos groupes (A, B, etc.).La fonction d'énumération de Java est bien plus utile et puissante que celle utilisée dans d'autres langages.Si vous n'êtes pas familier, consultez le Tutoriel Oracle.

La syntaxe simple consistant à définir vos propres énumérations fournit en fait une grande partie des fonctionnalités nécessaires pour résoudre cette question, éliminant ainsi certains codages compliqués.Nouveau syntaxe des littéraux pour les ensembles et les cartes dans le méthodes de fabrique de collections en Java 9 (JEP 269) rend le code encore plus simple maintenant.

Voici une application fonctionnelle complète. Notez le peu de code il y en a pour les algorithmes.La définition de vos propres énumérations personnalisées fait le gros du travail.

Une mise en garde concernant ce code d'application :Cela suppose que rien ne change dans les définitions de votre entreprise, ou du moins s'il y a un changement, vous ne vous souciez que des règles actuelles, « le plus récent est le meilleur ».Si vos règles changent au fil du temps et que vous devez représenter toutes les versions passées, présentes et futures, je créerais une application très différente, probablement avec une base de données pour stocker les règles.Mais cette application résout ici la question posée.

Season

Représentez votre saison sous forme d'énumération Season.Chaque objet de saison contient un List de Month enum objets qui définissent la durée de cette saison particulière.Le nouveau List.of La syntaxe ajoutée à Java 9 définit une liste immuable dans une syntaxe littérale via des méthodes d'usine statiques.

package com.basilbourque.watering;

import java.time.LocalDate;
import java.time.Month;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;

public enum Season
{
    SPRING( List.of( Month.MARCH , Month.APRIL ) ),
    SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),
    FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),
    WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );

    private List< Month > months;

    // Constructor
    Season ( List < Month > monthsArg )
    {
        this.months = monthsArg;
    }

    public List < Month > getMonths ( )
    {
        return this.months;
    }

    // For any given month, determine the season.
    static public Season ofLocalMonth ( Month monthArg )
    {
        Season s = null;
        for ( Season season : EnumSet.allOf( Season.class ) )
        {
            if ( season.getMonths().contains( monthArg ) )
            {
                s = season;
                break; // Bail out of this FOR loop.
            }
        }
        return s;
    }

    // For any given date, determine the season.
    static public Season ofLocalDate ( LocalDate localDateArg )
    {
        Month month = localDateArg.getMonth();
        Season s = Season.ofLocalMonth( month );
        return s;
    }

    // Run `main` for demo/testing.
    public static void main ( String[] args )
    {
        // Dump all these enum objects to console.
        for ( Season season : EnumSet.allOf( Season.class ) )
        {
            System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );
        }
    }
}

Group

Représentez chaque groupe de pelouses/cours de clients (A, B, C, D, E) sous la forme d'une énumération nommée Group.Chacun de ces objets enum contient un Map, mappant un Season enum objet à un Set de DayOfWeek énumérer les objets.Par exemple, Group.A dans Season.SPRING permet un arrosage sur deux jours, DayOfWeek.TUESDAY & DayOfWeek.THURSDAY.

package com.basilbourque.watering;

import java.time.DayOfWeek;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;

public enum Group
{
    A(
            Map.of(
                    Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
                    Season.WINTER , EnumSet.of( DayOfWeek.TUESDAY )
            )
    ),
    B(
            Map.of(
                    Season.SPRING , EnumSet.of( DayOfWeek.FRIDAY ) ,
                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,
                    Season.WINTER , EnumSet.of( DayOfWeek.FRIDAY )
            )
    ),
    C(
            Map.of(
                    Season.SPRING , EnumSet.of( DayOfWeek.MONDAY ) ,
                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
                    Season.FALL , EnumSet.of( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,
                    Season.WINTER , EnumSet.of( DayOfWeek.MONDAY )
            )
    ),
    D(
            Map.of(
                    Season.SPRING , EnumSet.of( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,
                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
                    Season.FALL , EnumSet.of( DayOfWeek.FRIDAY ) ,
                    Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )
            )
    ),
    E(
            Map.of(
                    Season.SPRING , EnumSet.of( DayOfWeek.TUESDAY ) ,
                    Season.SUMMER , EnumSet.allOf( DayOfWeek.class ) ,
                    Season.FALL , EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ,
                    Season.WINTER , EnumSet.of( DayOfWeek.WEDNESDAY )
            )
    );

    private Map < Season, Set < DayOfWeek > > map;

    // Constructor
    Group ( Map < Season, Set < DayOfWeek > > mapArg )
    {
        this.map = mapArg;
    }

    // Getter
    private Map < Season, Set < DayOfWeek > > getMapOfSeasonToDaysOfWeek() {
        return this.map ;
    }

    // Retrieve the DayOfWeek set for this particular Group.
    public Set<DayOfWeek> daysForSeason (Season season ) {
        Set<DayOfWeek> days =   this.map.get( season ) ; // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.
        return days;
    }



    // Run `main` for demo/testing.
    public static void main ( String[] args )
    {
        // Dump all these enum objects to console.
        for ( Group group : EnumSet.allOf( Group.class ) )
        {
            System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );
        }
    }

}

Schedule

Rassemblez tout cela dans ce Schedule classe.

Cette classe utilise les deux énumérations définies ci-dessus pour effectuer un travail utile.La seule méthode mise en œuvre jusqu'à présent vous indique quels jours de la semaine sont autorisés pour un groupe particulier à une date particulière.La méthode détermine lequel Season s'applique à cette date.

Exécutez le main méthode ici pour vider le contenu de nos deux énumérations et signaler les jours de la semaine permettant l'arrosage dans chaque groupe pour une date particulière codée en dur.

package com.basilbourque.watering;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import java.util.EnumSet;
import java.util.Set;

public class Schedule
{
    static private DateTimeFormatter isoWeekFormatter = DateTimeFormatter.ofPattern( "uuuu-'W'ww" ) ;

    static public Set < DayOfWeek > daysForGroupOnDate ( Group group , LocalDate localDate )
    {
        Season season = Season.ofLocalDate( localDate );
        Set < DayOfWeek > days = group.daysForSeason( season );
        return days;
    }

    // Run `main` for demo/testing.
    public static void main ( String[] args )
    {
        Season.main( null  );
        Group.main( null  );
        // Dump all these enum objects to console.
        for ( Group group : EnumSet.allOf( Group.class ) )
        {
            LocalDate localDate = LocalDate.now( ZoneId.of( "Africa/Tunis" ) );
            Set < DayOfWeek > days = Schedule.daysForGroupOnDate( group , localDate );
            String week = localDate.format( Schedule.isoWeekFormatter  ) ; // Standard ISO 8601 week, where week number one has the first Thursday of the calendar year, and week starts on Monday, so year is either 52 or 53 weeks long.
            String message = "Group " + group + " – Watering days on " + localDate + " week # " + week + " is: " + days;
            System.out.println( message );
        }
    }
}

Console

Lors de l'exécution Schedule.main, nous voyons cela transféré sur la console.

Saison:PRINTEMPS = [MARS, AVRIL]

Saison:ÉTÉ = [MAI, JUIN, JUILLET, AOÛT]

Saison:AUTOMNE = [SEPTEMBRE, OCTOBRE]

Saison:HIVER = [NOVEMBRE, DÉCEMBRE, JANVIER, FÉVRIER]

Groupe:A = {PRINTEMPS=[MARDI, JEUDI], AUTOMNE=[MARDI, JEUDI], ÉTÉ=[LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE], HIVER=[MARDI]}

Groupe:B = {PRINTEMPS=[VENDREDI], AUTOMNE=[MARDI, VENDREDI], ÉTÉ=[LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE], HIVER=[VENDREDI]}

Groupe:C = {PRINTEMPS=[LUNDI], AUTOMNE=[LUNDI, MARDI], ÉTÉ=[LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE], HIVER=[LUNDI]}

Groupe:D = {PRINTEMPS=[MERCREDI, VENDREDI], AUTOMNE=[VENDREDI], ÉTÉ=[LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE], HIVER=[MERCREDI]}

Groupe:E = {PRINTEMPS=[MARDI], AUTOMNE=[MARDI, MERCREDI], ÉTÉ=[LUNDI, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE], HIVER=[MERCREDI]}

Groupe A – Les jours d’arrosage de la semaine 2018-01-30 # 2018-W05 sont :[MARDI]

Groupe B – Les jours d’arrosage de la semaine 2018-01-30 # 2018-W05 sont :[VENDREDI]

Groupe C – Les jours d’arrosage de la semaine 2018-01-30 # 2018-W05 sont :[LUNDI]

Groupe D – Les jours d’arrosage de la semaine 2018-01-30 # 2018-W05 sont :[MERCREDI]

Groupe E – Les jours d’arrosage de la semaine 2018-01-30 # 2018-W05 sont :[MERCREDI]

Semaine ISO 8601

Il vous sera peut-être utile d'en apprendre davantage sur OIN 8601 norme pour un définition de la semaine.La norme donne une signification spécifique au terme « semaine » et définit un format textuel pour représenter une semaine particulière ou un jour particulier de cette semaine.

Pour travailler avec de telles semaines dans Java, pensez à ajouter le TroisDix-Extra bibliothèque à votre projet pour utiliser la YearWeek classe.

LocalDate

Le LocalDate La classe représente une valeur de date uniquement sans heure et sans fuseau horaire.

Un fuseau horaire est crucial pour déterminer une date.À un moment donné, la date varie à travers le monde selon la zone.Par exemple, quelques minutes après minuit Paris, France est un nouveau jour alors qu'il était encore « hier » Montreal, Quebec.

Si aucun fuseau horaire n'est spécifié, la JVM applique implicitement son fuseau horaire par défaut actuel.Cette valeur par défaut peut changer à tout moment, vos résultats peuvent donc varier.Mieux vaut spécifier explicitement votre fuseau horaire souhaité/attendu comme argument.

Spécifiez un nom de fuseau horaire correct sous la forme de continent/region, tel que America/Montreal, Africa/Casablanca, ou Pacific/Auckland.N'utilisez jamais l'abréviation de 3 à 4 lettres telle que EST ou IST comme ils sont pas de vrais fuseaux horaires, non standardisés, et même pas uniques (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

Si vous souhaitez utiliser le fuseau horaire par défaut actuel de la JVM, demandez-le et transmettez-le en argument.En cas d'omission, la valeur par défaut actuelle de la JVM est appliquée implicitement.Mieux vaut être explicite.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Ou précisez une date.Vous pouvez définir le mois par un nombre, avec une numérotation raisonnable de 1 à 12 pour janvier à décembre.

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

Ou, mieux, utilisez le Month enum objets prédéfinis, un pour chaque mois de l'année.Conseil:Utilisez ceux-ci Month objets dans votre base de code plutôt qu'un simple nombre entier pour rendre votre code plus auto-documenté, garantir des valeurs valides et fournir type-sécurité.

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

Collections immuables

Les listes, ensembles et cartes présentés ci-dessus devraient idéalement être des collections immuables, car modifier la composition de ces collections est susceptible d'être source de confusion et d'erreur.

La nouvelle syntaxe Java 9 List.of et Map.of sont déjà promis à être immuables.Cependant, dans notre cas, le Map devrait idéalement être un EnumMap pour l’efficacité des performances et de la mémoire.La mise en œuvre actuelle de Map.of et Set.of ne détecte apparemment pas l'utilisation d'énumérations en tant que membres et optimise automatiquement avec une utilisation interne de EnumMap et EnumSet.Il existe un problème OpenJDK ouvert pour prendre en compte ces problèmes : envisager des améliorations à EnumMap et EnumSet.

Une façon d'obtenir un EnumSet immuable et un EnumMap immuable consiste à utiliser Google Goyave bibliothèque:

Les résultats de chacun utilisent un sous-jacent EnumSet/EnumMap.Des opérations telles que get et put lancer une exception.Vous obtenez ainsi les optimisations liées à l'énumération ainsi que l'immuabilité.

Voici les Season et Group classes vues ci-dessus modifiées pour utiliser la bibliothèque Google Guava 23.6.

Season avec immuabilité

package com.basilbourque.watering;

import java.time.LocalDate;
import java.time.Month;
import java.util.EnumSet;
import java.util.List;

public enum Season
{
    SPRING( List.of( Month.MARCH , Month.APRIL ) ),  // `List.of` provides literals-style syntax, and returns an immutable `List`. New in Java 9.
    SUMMER( List.of( Month.MAY , Month.JUNE, Month.JULY , Month.AUGUST ) ),
    FALL( List.of( Month.SEPTEMBER , Month.OCTOBER ) ),
    WINTER( List.of( Month.NOVEMBER , Month.DECEMBER , Month.JANUARY , Month.FEBRUARY ) );

    private List< Month > months;

    // Constructor
    Season ( List < Month > monthsArg )
    {
        this.months = monthsArg;
    }

    public List < Month > getMonths ( )
    {
        return this.months;
    }

    // For any given month, determine the season.
    static public Season ofLocalMonth ( Month monthArg )
    {
        Season s = null;
        for ( Season season : EnumSet.allOf( Season.class ) )
        {
            if ( season.getMonths().contains( monthArg ) )
            {
                s = season;
                break; // Bail out of this FOR loop.
            }
        }
        return s;
    }

    // For any given date, determine the season.
    static public Season ofLocalDate ( LocalDate localDateArg )
    {
        Month month = localDateArg.getMonth();
        Season s = Season.ofLocalMonth( month );
        return s;
    }

    // Run `main` for demo/testing.
    public static void main ( String[] args )
    {
        // Dump all these enum objects to console.
        for ( Season season : EnumSet.allOf( Season.class ) )
        {
            System.out.println( "Season: " + season.toString() + " = " + season.getMonths() );
        }
    }
}

Group avec immuabilité

package com.basilbourque.watering;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.time.DayOfWeek;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;

public enum Group
{
    A(
            Maps.immutableEnumMap(
                    Map.of(  // `Map.of` provides literals-style syntax, and returns an immutable `Map`. New in Java 9.
                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.THURSDAY ) ,
                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.TUESDAY )
                    )
            )
    ),

    B(
            Maps.immutableEnumMap(
                    Map.of(
                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,
                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.TUESDAY , DayOfWeek.FRIDAY ) ,
                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.FRIDAY )
                    )
            )
    ),

    C(
            Maps.immutableEnumMap(
                    Map.of(
                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.MONDAY ) ,
                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.MONDAY , DayOfWeek.TUESDAY ) ,
                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.MONDAY )
                    )
            )
    ),

    D(
            Maps.immutableEnumMap(
                    Map.of(
                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY , DayOfWeek.FRIDAY ) ,
                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
                            Season.FALL , Sets.immutableEnumSet( DayOfWeek.FRIDAY ) ,
                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )
                    )
            )
    ),

    E(
            Maps.immutableEnumMap(
                    Map.of(
                            Season.SPRING , Sets.immutableEnumSet( DayOfWeek.TUESDAY ) ,
                            Season.SUMMER , Sets.immutableEnumSet( EnumSet.allOf( DayOfWeek.class ) ) ,
                            Season.FALL , Sets.immutableEnumSet( EnumSet.of( DayOfWeek.TUESDAY , DayOfWeek.WEDNESDAY ) ) ,
                            Season.WINTER , Sets.immutableEnumSet( DayOfWeek.WEDNESDAY )
                    )
            )
    );

    private Map < Season, Set < DayOfWeek > > map;

    // Constructor
    Group ( Map < Season, Set < DayOfWeek > > mapArg )
    {
        this.map = mapArg;
    }

    // Getter
    private Map < Season, Set < DayOfWeek > > getMapOfSeasonToDaysOfWeek ( )
    {
        return this.map;
    }

    // Retrieve the DayOfWeek set for this particular Group.
    public Set < DayOfWeek > daysForSeason ( Season season )
    {
        Set < DayOfWeek > days = this.map.get( season ); // Retrieve the value (set of days) for this key (a season) for this particular grouping of lawns/yards.
        return days;
    }

    // Run `main` for demo/testing.
    public static void main ( String[] args )
    {
        // Dump all these enum objects to console.
        for ( Group group : EnumSet.allOf( Group.class ) )
        {
            System.out.println( "Group: " + group.toString() + " = " + group.getMapOfSeasonToDaysOfWeek() );
        }
    }

}

À propos de java.time

Le java.time Le framework est intégré à Java 8 et versions ultérieures.Ces cours supplantent les vieux pénibles héritage cours date-heure tels que java.util.Date, Calendar, & SimpleDateFormat.

Le Joda-Time projet, maintenant en Mode de Maintenance, conseille la migration vers le java.time Des classes.

Pour en savoir plus, consultez le Tutoriel Oracle.Et recherchez Stack Overflow pour de nombreux exemples et explications.La spécification est JSR310.

Où obtenir les classes java.time ?

  • Java SE 8, JavaSE9, et ensuite
    • Intégré.
    • Fait partie de l'API Java standard avec une implémentation groupée.
    • Java 9 ajoute quelques fonctionnalités et correctifs mineurs.
  • JavaSE6 et JavaSE7
    • Une grande partie des fonctionnalités de java.time est rétroportée vers Java 6 et 7 dans ThreeTen-Backport.
  • Android
    • Versions ultérieures des implémentations du bundle Android des classes java.time.
    • Pour les versions antérieures d'Android, le TroisDixABP le projet s'adapte ThreeTen-Backport (mentionné ci-dessus).Voir Comment utiliser ThreeTenABP….

Le TroisDix-Extra le projet étend java.time avec des classes supplémentaires.Ce projet est un terrain d'essai pour d'éventuels futurs ajouts à java.time.Vous pouvez trouver ici des cours utiles tels que Interval, YearWeek, YearQuarter, et plus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top