Pergunta

Isso é desagradável para mim...Sou um cara de PHP e trabalho em Java em um projeto JSP.Eu sei como fazer o que estou tentando com muito código e uma completa falta de sutileza.

Eu prefiro fazer isso direito.Aqui está a situação:

Estou escrevendo um pequeno display para mostrar aos clientes em que dias eles podem regar seus gramados com base no grupo de irrigação (ABCDE) e em que época do ano estamos.Nossas temporadas são assim:Verão (5-1 a 8-31) Primavera (3-1 a 4-30) outono (9-1 a 10-31) inverno (11-1 a 2-28)

Um exemplo pode ser:

Se eu estiver no grupo A, aqui estão meus horários permitidos:Inverno:Segundas -feiras apenas primavera:Terça, quinta, Sáb Summer:Qualquer dia de outono:Terça, Quinta, Sábado

Se eu estivesse escrevendo isso em PHP, usaria arrays como este:

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

EU PODERIA fazer os arrays de dias (array("Tuesday","Thursday","Saturday")) etc, mas não é necessário para o que realmente estou tentando realizar.

Também precisarei configurar matrizes para determinar em que temporada estou:

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

Alguém pode sugerir uma maneira muito legal de fazer isso?Terei a data de hoje e a carta do grupo.Precisarei sair da minha função um dia (M) ou uma série de dias (tTS), (Qualquer).

Foi útil?

Solução

Você poderia fazer essencialmente o mesmo código com Hashtables (ou algum outro 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...

Não é tão elegante, mas Java não é uma linguagem dinâmica e não possui hashes no nível da linguagem.

Observação:Você pode conseguir uma solução melhor, isso surgiu na minha cabeça enquanto lia sua pergunta.

Outras dicas

Não tente ser tão dinâmico quanto o PHP.Você poderia tentar primeiro definir o que você precisa.

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

E por favor, leia a documentação do Tabela hash antes de usá-lo.Esta classe é sincronizada, o que significa que cada chamada é protegida contra multithreading, o que realmente retarda o acesso quando você não precisa de proteção extra.Por favor, use qualquer Mapa implementação em vez disso, como HashMap ou ÁrvoreMapa.

Parece que todo mundo está tentando encontrar a maneira Java de fazer isso como você está fazendo em PHP, em vez da maneira como deveria ser feito em Java.Considere cada parte do seu array como um objeto ou, pelo menos, o primeiro nível do array como um objeto e cada subnível como variáveis ​​dentro do objeto.Eles criam uma estrutura de dados que você preenche com esses objetos e acessa os objetos por meio dos acessadores fornecidos pela estrutura de dados.

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

É claro que isso provavelmente também não está certo.Eu faria de cada estação um objeto, e talvez de cada lista de dias da semana também.De qualquer forma, é mais facilmente reutilizado, compreendido e extensível do que um Hashtable confuso que tenta imitar seu código PHP.É claro que o PHP também possui objetos, e você deve usá-los de maneira semelhante, em vez de seus uber-arrays, sempre que possível.Eu entendo a tentação de trapacear, no entanto.PHP torna tudo tão fácil e divertido!

Aqui está uma maneira poderia parece, você pode descobrir o 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 );

Não sou um programador Java, mas me afasto do Java e penso apenas em termos que são mais independentes da linguagem - uma maneira mais limpa de fazer isso seria usar constantes ou tipos enumerados.Isso deve funcionar em qualquer idioma que suporte matrizes multidimensionais.

Se estiver usando constantes nomeadas, onde, por exemplo:

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

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

Então as constantes servem como subscritos de array mais legíveis:

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

Não sei por que alguns de vocês parecem pensar que jogar montes de objetos no código é o caminho a percorrer.Por exemplo, existem exatamente quatro estações, e elas não fazer ou loja qualquer coisa.Como simplificar alguma coisa para torná-los objetos?Wing está certo ao dizer que estes provavelmente deveriam ser constantes (ou talvez enums).

O que Bruce precisa, no fundo, é simplesmente uma tabela de pesquisa.Ele não precisa de uma hierarquia de objetos e interfaces;ele precisa de uma maneira de consultar uma programação com base em uma temporada e um identificador de grupo.Transformar coisas em objetos só faz sentido se tiverem responsabilidades ou estado.Se não tiverem nenhum dos dois, serão simplesmente identificadores, e construir objetos especiais para eles apenas aumentará a base de código.

Você poderia construir, por exemplo, Group objetos que contêm, cada um, um conjunto de sequências de programação (uma para cada temporada), mas se todos os Group object faz é fornecer funcionalidade de pesquisa, então você reinventou a tabela de pesquisa de uma forma muito menos intuitiva.Se ele tiver que procurar o grupo e depois consultar o cronograma, tudo o que ele terá é uma tabela de pesquisa em duas etapas que demorou mais para ser codificada, tem maior probabilidade de apresentar erros e será mais difícil de manter.

Estou com aqueles que sugerem encapsular funções em 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:Além disso, seus intervalos de datas não levam em consideração anos bissextos:

Nossas temporadas são assim:Verão (5-1 a 8-31) Primavera (3-1 a 4-30) outono (9-1 a 10-31) inverno (11-1 a 2-28)

Concordo que você definitivamente deveria colocar essa lógica por trás da interface limpa de:

public String lookupDays(String group, String date);

mas talvez você deva colocar os dados em um arquivo de propriedades.Não sou contra codificar esses dados em seus arquivos de origem, mas, como você notou, Java pode ser bastante prolixo quando se trata de coleções aninhadas.Seu arquivo pode ser parecido com:

A.Verão=M
A.Primavera=tTS
B.Verão=T

Normalmente não gosto de mover dados estáticos como este para um arquivo externo porque aumenta a "distância" entre os dados e o código que os utiliza.No entanto, sempre que você estiver lidando com coleções aninhadas, especialmente mapas, as coisas podem ficar muito feias, muito rápido.

Se você não gosta dessa ideia, talvez você possa fazer algo assim:

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

}

Você perde alguma legibilidade, mas pelo menos os dados ficam mais próximos de onde serão usados.

A "data" precisa ser um parâmetro?Se você estiver apenas mostrando o cronograma de irrigação atual, a própria classe WateringSchedule poderá descobrir que dia é hoje e, portanto, em que estação do ano estamos.Depois é só ter um método que retorne um mapa onde a Chave é a letra do grupo.Algo como:

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

Então na página JSP

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

Se precisar mostrar os horários de mais de uma temporada, você deve ter um método na classe WateringSchedule que retorne um mapa onde Seasons são as chaves e depois Maps of groupToScheduledDays são os valores.

Uma solução melhor seria talvez colocar todos esses dados em um banco de dados, em vez de codificá-los em suas fontes ou usar arquivos de propriedades.

Usar um banco de dados será muito mais fácil de manter, e há uma variedade de livre base de dados motores para escolher.

Dois desses mecanismos de banco de dados são implementados inteiramente em Java e podem ser incorporados em um aplicativo apenas incluindo um arquivo jar.É um pouco pesado, claro, mas é muito mais escalonável e mais fácil de manter.Só porque existem 20 registros hoje não significa que não haverá mais posteriormente devido a alterações de requisitos ou aumento de recursos.

Se, em algumas semanas ou meses, você decidir adicionar, digamos, restrições de irrigação por horário, será muito mais fácil adicionar essa funcionalidade se você já estiver usando um banco de dados.Mesmo que isso nunca aconteça, você passou algumas horas aprendendo como incorporar um banco de dados em um aplicativo.

Não existe uma solução bonita.Java simplesmente não faz coisas assim bem.A solução de Mike é basicamente a maneira de fazer isso se você quiser strings como índices (chaves).Outra opção se a configuração do hash de hashes for muito feia é anexar as strings (roubadas descaradamente de Mike e modificadas):

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

e depois pesquise:

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

Se você está insatisfeito com a feiúra geral (e não culpo você), coloque tudo isso atrás de uma chamada de método:

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

dr.

Usando recursos e classes modernas da linguagem Java, defina suas próprias enumerações para representar as estações e os grupos.

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

Esse método produz um Set de DayOfWeek objetos enum (não mero texto!), como DayOfWeek.TUESDAY & DayOfWeek.THURSDAY.

Java moderno

Alguém pode sugerir uma maneira muito legal de fazer isso?

Sim.

O Java moderno possui classes, coleções e enumerações integradas para ajudá-lo com esse problema.

O java.time framework embutido em Java oferece a Month enum e DayOfWeek enum.

O EnumSet e EnumMap fornecer implementações de Set e Map que são otimizados para uso com enums para execução rápida em muito pouca memória.

Você pode definir o seu próprio enumerações para representar sua temporada e seus grupos (A, B e assim por diante).O recurso enum em Java é muito mais útil e poderoso do que visto em outras linguagens.Se não estiver familiarizado, consulte o Tutorial Oráculo.

A sintaxe simples de definir suas próprias enumerações, na verdade, fornece grande parte da funcionalidade necessária para resolver esta questão, eliminando algumas codificações complicadas.Novo sintaxe de literais para conjuntos e mapas no métodos de fábrica de coleções em Java 9 (PEC 269) torna o código ainda mais simples agora.

Aqui está um aplicativo funcional completo. Observe quão pouco código existe para algoritmos.Definir suas próprias enumerações personalizadas faz a maior parte do trabalho pesado.

Uma advertência com este código de aplicativo:Ele pressupõe que nada muda nas definições de seu negócio ou, pelo menos, se houver uma mudança, você só se preocupa com as regras atuais, “o mais recente é o melhor”.Se suas regras mudarem com o tempo e você precisar representar todas as versões passadas, presentes e futuras, eu construiria um aplicativo bem diferente, provavelmente com um banco de dados para armazenar as regras.Mas este aplicativo aqui resolve a questão conforme perguntada.

Season

Represente sua temporada como um enum Season.Cada objeto de temporada contém um List de Month objetos enum que definem a duração daquela temporada específica.O novo List.of A sintaxe adicionada ao Java 9 define uma lista imutável em uma sintaxe literal por meio de métodos estáticos de fábrica.

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

Represente cada agrupamento de gramados/quintais dos clientes (A, B, C, D, E) como um enum denominado Group.Cada um desses objetos enum contém um Map, mapeando um Season objeto enum para um Set de DayOfWeek objetos enum.Por exemplo, Group.A em Season.SPRING permite regar em dois dias, 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

Junte tudo isso Schedule aula.

Esta classe faz uso dos dois enums definidos acima para realizar um trabalho útil.O único método implementado até agora informa quais dias da semana são permitidos para um determinado grupo em uma determinada data.O método determina qual Season aplica-se a essa data.

Execute o main método aqui para despejar o conteúdo de nossos dois enums e relatar os dias da semana permitindo a rega em cada grupo para uma data específica codificada.

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

Ao correr Schedule.main, vemos isso sendo despejado no console.

Temporada:PRIMAVERA = [MARÇO, ABRIL]

Temporada:VERÃO = [MAIO, JUNHO, JULHO, AGOSTO]

Temporada:OUTONO = [SETEMBRO, OUTUBRO]

Temporada:INVERNO = [NOVEMBRO, DEZEMBRO, JANEIRO, FEVEREIRO]

Grupo:A = {PRIMAVERA=[TERÇA, QUINTA], OUTONO=[TERÇA, QUINTA], VERÃO=[SEGUNDA, TERÇA, QUARTA, QUINTA, SEXTA, SÁBADO, DOMINGO], INVERNO=[TERÇA]}

Grupo:B = {PRIMAVERA=[SEXTA-FEIRA], OUTONO=[TERÇA, SEXTA], VERÃO=[SEGUNDA, TERÇA, QUARTA, QUINTA, SEXTA, SÁBADO, DOMINGO], INVERNO=[SEXTA-FEIRA]}

Grupo:C = {PRIMAVERA=[SEGUNDA-FEIRA], OUTONO=[SEGUNDA-FEIRA, TERÇA-FEIRA], VERÃO=[SEGUNDA-FEIRA, TERÇA-FEIRA, QUARTA-FEIRA, QUINTA-FEIRA, SEXTA-FEIRA, SÁBADO, DOMINGO], INVERNO=[SEGUNDA-FEIRA]}

Grupo:D = {PRIMAVERA=[QUARTA, SEXTA], OUTONO=[SEXTA], VERÃO=[SEGUNDA, TERÇA, QUARTA, QUINTA, SEXTA, SÁBADO, DOMINGO], INVERNO=[QUARTA-FEIRA]}

Grupo:E = {PRIMAVERA=[TERÇA], OUTONO=[TERÇA, QUARTA], VERÃO=[SEGUNDA, TERÇA, QUARTA, QUINTA, SEXTA, SÁBADO, DOMINGO], INVERNO=[QUARTA-FEIRA]}

Grupo A – Os dias de rega na semana 30/01/2018 # 2018-W05 são:[TERÇA-FEIRA]

Grupo B – Os dias de rega na semana 30/01/2018 # 2018-W05 são:[SEXTA-FEIRA]

Grupo C - Os dias de rega na semana 30/01/2018 # 2018-W05 são:[SEGUNDA-FEIRA]

Grupo D – Os dias de rega na semana 30/01/2018 # 2018-W05 são:[QUARTA-FEIRA]

Grupo E – Os dias de rega na semana 30/01/2018 # 2018-W05 são:[QUARTA-FEIRA]

Semana ISO 8601

Você pode achar útil aprender sobre o ISO 8601 padrão para um definição de semana.A norma dá um significado específico a “semana” e define um formato textual para representar uma determinada semana ou um determinado dia dentro dessa semana.

Para trabalhar com essas semanas em Java, considere adicionar o Três Dez-Extra biblioteca ao seu projeto para fazer uso do YearWeek aula.

LocalDate

O LocalDate class representa um valor somente de data, sem hora do dia e sem fuso horário.

Um fuso horário é crucial para determinar uma data.Para qualquer momento, a data varia em todo o mundo por zona.Por exemplo, alguns minutos depois da meia-noite em Paris, França é um novo dia enquanto ainda “ontem” em Montreal Quebec.

Se nenhum fuso horário for especificado, a JVM aplicará implicitamente seu fuso horário padrão atual.Esse padrão pode mudar a qualquer momento, portanto seus resultados podem variar.Melhor especificar explicitamente o fuso horário desejado/esperado como argumento.

Especifique um nome correto do fuso horário no formato de continent/region, como America/Montreal, Africa/Casablanca, ou Pacific/Auckland.Nunca use abreviações de 3 a 4 letras, como EST ou IST como eles são não fusos horários verdadeiros, não padronizados e nem mesmo únicos (!).

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

Se você quiser usar o fuso horário padrão atual da JVM, solicite-o e passe-o como argumento.Se omitido, o padrão atual da JVM será aplicado implicitamente.Melhor ser explícito.

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

Ou especifique uma data.Você pode definir o mês por um número, com numeração sensata de 1 a 12 para janeiro a dezembro.

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 melhor, use o Month objetos enum pré-definidos, um para cada mês do ano.Dica:Use estes Month objetos em toda a sua base de código, em vez de um mero número inteiro, para tornar seu código mais autodocumentado, garantir valores válidos e fornecer segurança de tipo.

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

Coleções imutáveis

As listas, conjuntos e mapas vistos acima deveriam ser, idealmente, coleções imutáveis, pois alterar a associação dessas coleções provavelmente será confuso e errôneo.

A nova sintaxe do Java 9 List.of e Map.of já estão prometidos para serem imutáveis.Contudo, no nosso caso o Map idealmente deveria ser um EnumMap para eficiência de desempenho e memória.A atual implementação do Map.of e Set.of aparentemente não detecta o uso de enums como membros e otimiza automaticamente com um uso interno de EnumMap e EnumSet.Há um problema do OpenJDK aberto para considerar tais questões: considere melhorias no EnumMap e EnumSet.

Uma maneira de obter um EnumSet imutável e um EnumMap imutável é através do Google Goiaba biblioteca:

Os resultados de cada um usam um subjacente EnumSet/EnumMap.Operações como get e put lançar uma exceção.Assim, você obtém as otimizações relacionadas à enum junto com a imutabilidade.

Aqui está o Season e Group classes vistas acima modificadas para usar a biblioteca Google Guava 23.6.

Season com imutabilidade

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 com imutabilidade

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

}

Sobre java.time

O java.time framework é integrado ao Java 8 e posterior.Essas aulas substituem as velhas e problemáticas legado classes de data e hora, como java.util.Date, Calendar, & SimpleDateFormat.

O Hora Joda projeto, agora em Modo de manutenção, aconselha a migração para o java.time Aulas.

Para saber mais, consulte o Tutorial Oráculo.E pesquise no Stack Overflow muitos exemplos e explicações.A especificação é JSR 310.

Onde obter as classes java.time?

  • Java SE 8, Java SE 9, e depois
    • Construídas em.
    • Parte da API Java padrão com uma implementação agrupada.
    • Java 9 adiciona alguns recursos e correções menores.
  • Java SE 6 e Java SE 7
    • Grande parte da funcionalidade java.time é portada para Java 6 e 7 em ThreeTen-Backport.
  • Android
    • Versões posteriores de implementações de pacotes Android das classes java.time.
    • Para Android anterior, o TrêsTenABP projeto se adapta ThreeTen-Backport (Mencionado acima).Ver Como usar o ThreeTenABP….

O Três Dez-Extra projeto estende java.time com classes adicionais.Este projeto é um campo de provas para possíveis adições futuras ao java.time.Você pode encontrar algumas classes úteis aqui, como Interval, YearWeek, YearQuarter, e mais.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top