Pregunta

Esto es desagradable para mí...Soy un chico de PHP que trabaja en Java en un proyecto JSP.Sé cómo hacer lo que intento con demasiado código y una total falta de delicadeza.

Preferiría hacerlo bien.Aquí está la situación:

Estoy escribiendo una pequeña presentación para mostrar a los clientes qué días pueden regar su césped según su grupo de riego (ABCDE) y en qué época del año es.Nuestras estaciones se ven así:Summer (5-1 a 8-31) primavera (3-1 a 4-30) otoño (9-1 a 10-31) Invierno (11-1 a 2-28)

Un ejemplo podría ser:

Si estoy en el grupo A, estos serían mis tiempos permitidos:Invierno:Lunes solo primavera:Martes, jueves, sábado verano:Cualquier día de otoño:martes, jueves, sábado

Si estuviera escribiendo esto en PHP usaría matrices como esta:

//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';

PODRÍA hacer las matrices de días (matriz ("Martes", "Jueves", "Sábado")), etc., pero no es necesario para lo que realmente estoy tratando de lograr.

También necesitaré configurar matrices para determinar en qué temporada estoy:

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

¿Alguien puede sugerir una forma realmente interesante de hacer esto?Tendré la fecha de hoy y la carta del grupo.Necesitaré salir de mi función un día (M) o una serie de días (tTS), (Cualquiera).

¿Fue útil?

Solución

Podrías hacer esencialmente el mismo código con Hashtables (o algún otro mapa):

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

No es tan elegante, pero claro, Java no es un lenguaje dinámico y no tiene hashes a nivel de lenguaje.

Nota:Es posible que puedas encontrar una mejor solución, esto me vino a la cabeza cuando leí tu pregunta.

Otros consejos

No intentes ser tan dinámico como lo es PHP.Podrías intentarlo primero definir Que necesitas.

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);
}

Y por favor, lea la documentación de Tabla de picadillo antes de usarlo.Esta clase está sincronizada, lo que significa que cada llamada está protegida contra subprocesos múltiples, lo que realmente ralentiza el acceso cuando no se necesita protección adicional.Por favor use cualquier Mapa implementación en lugar como HashMap o ÁrbolMapa.

Parece que todo el mundo está tratando de encontrar la forma Java de hacerlo como si lo hiciera en PHP, en lugar de la forma en que debería hacerse en Java.Simplemente considere cada parte de su matriz como un objeto o, al menos, el primer nivel de la matriz como un objeto y cada subnivel como variables dentro del objeto.Construya una estructura de datos que complete con dichos objetos y acceda a los objetos a través de los descriptores de acceso proporcionados por la estructura de datos.

Algo como:

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);
...

Por supuesto, eso probablemente tampoco sea correcto.Haría de cada estación un objeto, y tal vez de cada lista de días de la semana también como un objeto.De todos modos, es más fácil de reutilizar, comprender y ampliar que un Hashtable interconectado que intenta imitar su código PHP.Por supuesto, PHP también tiene objetos, y deberías usarlos de manera similar en lugar de tus súper matrices, siempre que sea posible.Sin embargo, entiendo la tentación de hacer trampa.¡PHP lo hace muy fácil y divertido!

He aquí una manera podría parece, puedes descubrir el resto:

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 );

No soy un programador de Java, pero me alejo de Java y solo pienso en términos que son más independientes del lenguaje; una forma más limpia de hacerlo podría ser usar constantes o tipos enumerados.Esto debería funcionar en cualquier idioma que admita matrices multidimensionales.

Si se utilizan constantes con nombre, donde, por ejemplo:

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

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

Entonces las constantes sirven como subíndices de matriz más legibles:

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

Usando tipos enumerados:

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";

No entiendo por qué algunos de ustedes parecen pensar que arrojar montones de objetos al código es el camino a seguir.Por ejemplo, hay exactamente cuatro estaciones y no hacer o almacenar cualquier cosa.¿Cómo se simplifica algo para convertirlos en objetos?Wing tiene razón en que probablemente deberían ser constantes (o tal vez enumeraciones).

Lo que Bruce necesita, en el fondo, es simplemente una tabla de búsqueda.No necesita una jerarquía de objetos e interfaces;necesita una forma de buscar un calendario basado en una temporada y un identificador de grupo.Convertir las cosas en objetos sólo tiene sentido si tienen responsabilidades o estado.Si no tienen ninguno de los dos, entonces son simplemente identificadores, y crear objetos especiales para ellos solo hace que el código base sea más grande.

podría construir, por ejemplo, Group objetos que contienen cada uno un conjunto de cadenas de programación (una para cada temporada), pero si todas las Group objeto es proporcionar funcionalidad de búsqueda, entonces habrá reinventado la tabla de búsqueda de una manera mucho menos intuitiva.Si tiene que buscar el grupo y luego buscar el cronograma, todo lo que tiene es una tabla de búsqueda de dos pasos que tomó más tiempo codificar, es más probable que tenga errores y será más difícil de mantener.

Estoy con aquellos que sugieren encapsular funciones en objetos.

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);
    }

}

EDITAR:Además, sus rangos de fechas no tienen en cuenta los años bisiestos:

Nuestras estaciones se ven así:Summer (5-1 a 8-31) primavera (3-1 a 4-30) otoño (9-1 a 10-31) Invierno (11-1 a 2-28)

Estoy de acuerdo en que definitivamente deberías poner esta lógica detrás de la interfaz limpia de:

public String lookupDays(String group, String date);

pero tal vez deberías guardar los datos en un archivo de propiedades.No estoy en contra de codificar estos datos en sus archivos fuente pero, como habrá notado, Java puede ser bastante prolijo cuando se trata de colecciones anidadas.Su archivo podría verse así:

A.Verano=M
A.Primavera=tTS
B.Verano=T

Por lo general, no me gusta mover datos estáticos como este a un archivo externo porque aumenta la "distancia" entre los datos y el código que los usa.Sin embargo, cuando se trata de colecciones anidadas, especialmente mapas, las cosas pueden ponerse muy feas y muy rápidamente.

Si no te gusta esta idea, tal vez puedas hacer algo como esto:

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);
  }

}

Se pierde algo de legibilidad, pero al menos los datos están más cerca de donde se van a utilizar.

¿La "fecha" tiene que ser un parámetro?Si solo está mostrando el programa de riego actual, la clase WateringSchedule puede determinar qué día es y, por lo tanto, qué estación es.Entonces solo tenga un método que devuelva un mapa donde la clave es la letra del grupo.Algo como:

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

Luego en la página JSP

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

Si necesita mostrar los horarios de más de una temporada, debe tener un método en la clase WateringSchedule que devuelva un mapa donde las estaciones son las claves y luego los mapas de groupToScheduledDays son los valores.

Quizás una mejor solución sería poner todos esos datos en una base de datos, en lugar de codificarlos en sus fuentes o usar archivos de propiedades.

Usar una base de datos será mucho más fácil de mantener y existen variedad de gratis base de datos Motores para elegir.

Dos de estos motores de bases de datos están implementados completamente en Java y pueden integrarse en una aplicación simplemente incluyendo un archivo jar.Es un poco pesado, claro, pero es mucho más escalable y más fácil de mantener.El hecho de que hoy haya 20 registros no significa que no habrá más más adelante debido a cambios en los requisitos o a la proliferación de funciones.

Si, en unas pocas semanas o meses, decide que desea agregar, digamos, restricciones de riego a la hora del día, será mucho más fácil agregar esa funcionalidad si ya está utilizando una base de datos.Incluso si eso nunca sucede, entonces habrá pasado algunas horas aprendiendo cómo integrar una base de datos en una aplicación.

No existe una solución bonita.Java simplemente no hace bien este tipo de cosas.La solución de Mike es prácticamente la forma de hacerlo si desea cadenas como índices (claves).Otra opción si la configuración hash-of-hashes es demasiado fea es unir las cadenas (descaradamente robadas de Mike y modificadas):

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

y luego buscar:

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

Si no estás satisfecho con la fealdad general (y no te culpo), ponlo todo detrás de una llamada al método:

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

tl; dr

Utilizando características y clases modernas del lenguaje Java, defina sus propias enumeraciones para representar las estaciones y los grupos.

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

Ese método produce un Set de DayOfWeek objetos de enumeración (¡no mero texto!), como DayOfWeek.TUESDAY & DayOfWeek.THURSDAY.

Java moderno

¿Alguien puede sugerir una forma realmente interesante de hacer esto?

Sí.

Java moderno tiene clases, colecciones y enumeraciones integradas para ayudarle con este problema.

El java.tiempo El marco integrado en Java ofrece la Month enumeración y DayOfWeek enumeración.

El EnumSet y EnumMap proporcionar implementaciones de Set y Map que están optimizados para su uso con enumeraciones para una ejecución rápida en muy poca memoria.

Puedes definir el tuyo enumeraciones para representar su temporada y sus grupos (A, B, etc.).La función de enumeración en Java es mucho más útil y poderosa que la que se ve en otros lenguajes.Si no está familiarizado, consulte el Tutorial de Oráculo.

La sintaxis simple de definir sus propias enumeraciones en realidad proporciona gran parte de la funcionalidad necesaria para resolver esta pregunta, eliminando parte de la codificación complicada.Nuevo sintaxis de literales para conjuntos y mapas en el métodos de fábrica de colecciones en Java 9 (JEP 269) hace que el código sea aún más simple ahora.

Aquí hay una aplicación de trabajo completa. Tenga en cuenta lo poco código hay para algoritmos.Definir sus propias enumeraciones personalizadas hace la mayor parte del trabajo pesado.

Una advertencia con el código de esta aplicación:Se supone que nada cambia en las definiciones de su negocio, o al menos si hay un cambio, solo le importan las reglas actuales, "lo último es lo mejor".Si sus reglas cambian con el tiempo y necesita representar todas las versiones pasadas, presentes y futuras, crearía una aplicación muy diferente, probablemente con una base de datos para almacenar las reglas.Pero esta aplicación aquí resuelve la pregunta tal como se formula.

Season

Representa tu temporada como una enumeración Season.Cada objeto de temporada tiene un List de Month objetos de enumeración que definen la duración de esa temporada en particular.El nuevo List.of La sintaxis agregada a Java 9 define una lista inmutable en una sintaxis literal a través de métodos de fábrica estáticos.

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

Representa cada grupo de céspedes/patios de clientes (A, B, C, D, E) como una enumeración denominada Group.Cada uno de estos objetos enum contiene un Map, mapeando un Season objeto de enumeración a un Set de DayOfWeek objetos de enumeración.Por ejemplo, Group.A en Season.SPRING permite regar en dos días, 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

Júntelo todo en esto Schedule clase.

Esta clase utiliza las dos enumeraciones definidas anteriormente para realizar un trabajo útil.El único método implementado hasta ahora le indica qué días de la semana están permitidos para un grupo particular en una fecha particular.El método determina cuál Season Aplica para esa fecha.

Ejecute el main método aquí para volcar el contenido de nuestras dos enumeraciones e informar sobre los días de la semana que permiten el riego en cada grupo para una fecha codificada particular.

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 );
        }
    }
}

Consola

al correr Schedule.main, vemos esto volcado a la consola.

Estación:PRIMAVERA = [MARZO, ABRIL]

Estación:VERANO = [MAYO, JUNIO, JULIO, AGOSTO]

Estación:OTOÑO = [SEPTIEMBRE, OCTUBRE]

Estación:INVIERNO = [NOVIEMBRE, DICIEMBRE, ENERO, FEBRERO]

Grupo:A = {PRIMAVERA=[MARTES, JUEVES], OTOÑO=[MARTES, JUEVES], VERANO=[LUNES, MARTES, MIÉRCOLES, JUEVES, VIERNES, SÁBADO, DOMINGO], INVIERNO=[MARTES]}

Grupo:B = {PRIMAVERA=[VIERNES], OTOÑO=[MARTES, VIERNES], VERANO=[LUNES, MARTES, MIÉRCOLES, JUEVES, VIERNES, SÁBADO, DOMINGO], INVIERNO=[VIERNES]}

Grupo:C = {PRIMAVERA=[LUNES], OTOÑO=[LUNES, MARTES], VERANO=[LUNES, MARTES, MIÉRCOLES, JUEVES, VIERNES, SÁBADO, DOMINGO], INVIERNO=[LUNES]}

Grupo:D = {PRIMAVERA=[MIÉRCOLES, VIERNES], OTOÑO=[VIERNES], VERANO=[LUNES, MARTES, MIÉRCOLES, JUEVES, VIERNES, SÁBADO, DOMINGO], INVIERNO=[MIÉRCOLES]}

Grupo:E = {PRIMAVERA=[MARTES], OTOÑO=[MARTES, MIÉRCOLES], VERANO=[LUNES, MARTES, MIÉRCOLES, JUEVES, VIERNES, SÁBADO, DOMINGO], INVIERNO=[MIÉRCOLES]}

Grupo A – Los días de riego del 2018-01-30 semana # 2018-W05 son:[MARTES]

Grupo B – Los días de riego del 2018-01-30 semana # 2018-W05 son:[VIERNES]

Grupo C – Los días de riego en la semana 2018-01-30 # 2018-W05 son:[LUNES]

Grupo D – Los días de riego en la semana 2018-01-30 # 2018-W05 son:[MIÉRCOLES]

Grupo E – Los días de riego en la semana 2018-01-30 # 2018-W05 son:[MIÉRCOLES]

Semana ISO 8601

Puede que le resulte útil aprender sobre el ISO 8601 estándar para un definicion de semana.La norma da un significado específico a "semana" y define un formato textual para representar una semana en particular o un día en particular dentro de esa semana.

Para trabajar con estas semanas dentro de Java, considere agregar el TresDiez-Extra biblioteca a su proyecto para hacer uso de la YearWeek clase.

LocalDate

El LocalDate La clase representa un valor de solo fecha sin hora del día y sin zona horaria.

Una zona horaria es crucial para determinar una fecha.Para un momento dado, la fecha varía en todo el mundo según la zona.Por ejemplo, unos minutos después de la medianoche en París, Francia es un nuevo día siendo todavía “ayer” en Montreal, Quebec.

Si no se especifica ninguna zona horaria, la JVM aplica implícitamente su zona horaria predeterminada actual.Ese valor predeterminado puede cambiar en cualquier momento, por lo que sus resultados pueden variar.Es mejor especificar explícitamente la zona horaria deseada/esperada como argumento.

Especifique un nombre de zona horaria adecuado en el formato de continent/region, como America/Montreal, Africa/Casablanca, o Pacific/Auckland.Nunca utilice abreviaturas de 3 o 4 letras como EST o IST ya que son no zonas horarias verdaderas, no estandarizadas y ni siquiera únicas (!).

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

Si desea utilizar la zona horaria predeterminada actual de la JVM, solicítela y pásela como argumento.Si se omite, el valor predeterminado actual de la JVM se aplica implícitamente.Es mejor ser explícito.

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

O especificar una fecha.Puede establecer el mes mediante un número, con la misma numeración del 1 al 12 para enero-diciembre.

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.

O, mejor, utilizar el Month objetos enum predefinidos, uno para cada mes del año.Consejo:Usa estos Month objetos en toda su base de código en lugar de un simple número entero para que su código sea más autodocumentado, garantice valores válidos y proporcione seguridad de tipo.

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

Colecciones inmutables

Idealmente, las listas, conjuntos y mapas vistos anteriormente deberían ser colecciones inmutables, ya que cambiar la membresía de esas colecciones probablemente resulte confuso y erróneo.

La nueva sintaxis de Java 9 List.of y Map.of Ya se ha prometido que serán inmutables.Sin embargo, en nuestro caso la Map idealmente debería ser un EnumMap para la eficiencia del rendimiento y la memoria.La implementación actual de Map.of y Set.of aparentemente no detecta el uso de enumeraciones como miembros y optimiza automáticamente con un uso interno de EnumMap y EnumSet.Hay un problema de OpenJDK abierto para considerar tales problemas: considerar mejoras en EnumMap y EnumSet.

Una forma de obtener un EnumSet inmutable y un EnumMap inmutable es a través de Google guayaba biblioteca:

Los resultados de cada uno utilizan un subyacente EnumSet/EnumMap.Operaciones como get y put lanzar una excepción.Entonces obtienes las optimizaciones relacionadas con la enumeración junto con la inmutabilidad.

Aquí están los Season y Group Las clases vistas arriba se modificaron para usar la biblioteca Google Guava 23.6.

Season con inmutabilidad

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 con inmutabilidad

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() );
        }
    }

}

Acerca de java.time

El java.tiempo framework está integrado en Java 8 y versiones posteriores.Estas clases reemplazan a las viejas y problemáticas legado clases de fecha y hora como java.util.Date, Calendar, & SimpleDateFormat.

El Tiempo Joda proyecto, ahora en modo de mantenimiento, aconseja la migración a la java.tiempo clases.

Para obtener más información, consulte el Tutorial de Oráculo.Y busque Stack Overflow para obtener muchos ejemplos y explicaciones.La especificación es JSR 310.

¿Dónde obtener las clases java.time?

  • JavaSE 8, Java SE 9, y después
    • Incorporado.
    • Parte de la API de Java estándar con una implementación incluida.
    • Java 9 agrega algunas características y correcciones menores.
  • JavaSE6 y JavaSE7
    • Gran parte de la funcionalidad java.time está adaptada a Java 6 y 7 en ThreeTen-Backport.
  • Androide
    • Versiones posteriores de implementaciones de paquetes de Android de las clases java.time.
    • Para Android anterior, el TresDiezABP el proyecto se adapta ThreeTen-Backport (mencionado anteriormente).Ver Cómo utilizar ThreeTenABP....

El TresDiez-Extra El proyecto extiende java.time con clases adicionales.Este proyecto es un campo de pruebas para posibles adiciones futuras a java.time.Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter, y más.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top