Сведения о вопросе

MAT

20:05, 28th August, 2020

Теги

java   php   jsp   tomcat    

Массивы массивов в Java

Просмотров: 541   Ответов: 12

Это очень неприятно для меня... Я парень PHP, работающий в Java над проектом JSP. Я знаю, как сделать то, что я пытаюсь через слишком много кода и полное отсутствие изящества.

Я бы предпочел сделать все правильно. Вот такая ситуация:

Я пишу небольшой дисплей, чтобы показать клиентам, в какие дни они могут поливать свои газоны на основе их группы полива (ABCDE) и в какое время года это происходит. Наши сезоны выглядят так: Лето (от 5-1 до 8-31) Spring (от 3-1 до 4-30) Падение (от 9-1 до 10-31) Зима (от 11-1 до 2-28)

Примером может быть:

Если бы я был в группе А, здесь были бы мои разрешенные времена: Зима: только по понедельникам Spring: Вт, Чт, Сб Лето: В Любой День Осень: Вт, Чт, Сб

Если бы я писал это в PHP, я бы использовал такие массивы:

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

Я мог бы сделать массивы дней (array ("Tuesday","Thursday","Saturday")) и т. д., Но это не обязательно для того, что я действительно пытаюсь выполнить.

Мне также нужно будет настроить массивы, чтобы определить, в каком сезоне я нахожусь:

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

Может ли кто-нибудь предложить действительно классный способ сделать это? У меня будет сегодняшняя дата и письмо группы. Мне нужно будет выйти из моей функции в день (M) или в ряд дней (tTS), (любой).



  Сведения об ответе

SILA

04:51, 1st August, 2020

Вы можете сделать по существу тот же код с хэш-таблицами (или какой-то другой картой):

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

Не так элегантно, но опять же, Java не является динамическим языком, и у него нет хэшей на уровне языка.

Примечание: Вы могли бы сделать лучшее решение, это просто выскочило у меня в голове, когда я прочитал Ваш вопрос.


  Сведения об ответе

piter

20:08, 2nd August, 2020

Не пытайтесь быть таким же динамичным, как PHP. Вы можете попробовать сначала определить , что вам нужно.

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

И, пожалуйста, прочитайте документацию Hashtable перед его использованием. Этот класс синхронизирован, что означает, что каждый вызов защищен от многопоточности, которая действительно замедляет доступ, когда вам не нужна дополнительная защита. Пожалуйста, используйте любую реализацию карты вместо HashMap или TreeMap .


  Сведения об ответе

ASER

05:37, 28th August, 2020

Похоже, что все пытаются найти способ Java, чтобы сделать это, как вы делаете это в PHP, а не так, как это должно быть сделано в Java. Просто рассматривайте каждую часть вашего массива как объект или, по крайней мере, первый уровень массива как объект, а каждый подуровень-как переменные внутри объекта. Построение структуры данных, которую вы заполняете указанными объектами, и доступ к объектам через заданные методы доступа структуры данных.

Что-то вроде:

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

Конечно, это, вероятно, тоже не правильно. Я бы сделал каждый сезон объектом, и, возможно,каждый будний день тоже был бы объектом. Во всяком случае, его легче повторно использовать, понимать и расширять, чем скованную хэш-таблицу, которая пытается имитировать ваш код PHP. Конечно, PHP также имеет объекты, и вы должны использовать их аналогичным образом вместо ваших uber-массивов, где это возможно. Хотя я понимаю искушение схитрить. PHP делает это так легко, и так весело!


  Сведения об ответе

PROGA

03:09, 18th August, 2020

Вот один из способов, как это может выглядеть, вы можете понять rest:

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


  Сведения об ответе

9090

14:46, 5th August, 2020

Я не программист Java, но уходя от Java и просто думая в терминах, которые являются более языковыми агностиками - более чистым способом сделать это может быть использование либо констант, либо перечислимых типов. Это должно работать в любом языке, который поддерживает многомерные массивы.

При использовании именованных констант, где, например:

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

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

Тогда константы служат в качестве более читаемых индексов массива:

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

Использование перечисленных типов:

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


  Сведения об ответе

fo_I_K

02:53, 12th August, 2020

Я совершенно не понимаю, почему некоторые из вас, кажется, думают, что бросать куски объектов в код-это путь. Например, есть ровно четыре сезона, и они ничего не делают и не хранят . Как это упрощает что-либо, чтобы сделать их объектами? Крыло совершенно верно, что они, вероятно, должны быть константами (или, может быть, enums).

То, что нужно Брюсу, в его сердце, - это просто таблица поиска. Ему не нужна иерархия объектов и интерфейсов; ему нужен способ поиска расписания на основе сезона и идентификатора группы. Превращение вещей в объекты имеет смысл только в том случае, если у них есть обязанности или государство. Если у них нет ни того, ни другого, то они просто идентификаторы, и создание специальных объектов для них просто делает кодовую базу больше.

Вы можете построить, например, объекты Group , каждый из которых содержит набор строк расписания (по одному для каждого сезона), но если все, что делает объект Group , - это функциональность поиска, то вы переосмыслили таблицу поиска гораздо менее интуитивно понятным способом. Если ему придется искать группу, а затем искать расписание, все, что у него есть,-это двухэтапная таблица поиска, которая заняла больше времени на кодирование, скорее всего, будет ошибочной и будет сложнее поддерживать.


  Сведения об ответе

dump

20:26, 28th August, 2020

Я с теми, кто предлагает инкапсулировать функцию в объекты.

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

}

EDIT: кроме того, ваши диапазоны дат не учитывают високосные годы:

Наши сезоны выглядят так: Лето (5-1 - 8-31) Spring (3-1 - 4-30) Осень (от 9-1 до 10-31) зима (от 11-1 до 2-28)


  Сведения об ответе

PROGA

14:53, 10th August, 2020

Я согласен, что вы должны определенно поставить эту логику за чистый интерфейс:

public String lookupDays(String group, String date);

но, возможно, вы должны вставить данные в файл свойств. Я не против жесткого кодирования этих данных в ваших исходных файлах, но, как вы заметили, Java может быть довольно многословным, когда речь заходит о вложенных коллекциях. Ваш файл может выглядеть так:

A.Summer=M
A.Spring=tTS
B.Summer=T

Обычно мне не нравится перемещать статические данные, подобные этому, во внешний файл, потому что это увеличивает "distance" между данными и кодом, который его использует. Однако всякий раз, когда вы имеете дело с вложенными коллекциями, особенно картами, все может стать очень уродливым, очень быстро.

Если вам не нравится эта идея, может быть, вы можете сделать что-то вроде этого:

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

}

Вы теряете некоторую читаемость, но, по крайней мере, данные ближе к тому, где они будут использоваться.


  Сведения об ответе

SILA

18:27, 23rd August, 2020

Возможно, лучшим решением было бы поместить все эти данные в базу данных, а не жестко кодировать их в своих источниках или использовать файлы свойств.

Использование базы данных будет намного проще в обслуживании, и есть множество бесплатных движков баз данных на выбор.

Два из этих движков баз данных полностью реализованы в Java и могут быть встроены в приложение, просто включив файл jar. Это немного тяжеловесно, конечно, но это намного более масштабируемо и проще в обслуживании. Просто потому, что есть 20 записей сегодня не означает, что не будет больше позже из-за изменения требований или функции ползучести.

Если через несколько недель или месяцев вы решите, что хотите добавить, скажем, ограничения по времени суток, вам будет гораздо проще добавить эту функциональность, Если вы уже используете базу данных. Даже если этого никогда не произойдет, вы потратили несколько часов, изучая, как встроить базу данных в приложение.


  Сведения об ответе

baggs

02:27, 12th August, 2020

Должен ли "date" быть параметром? Если вы просто показываете текущее расписание полива, класс WateringSchedule сам может определить, какой сегодня день и, следовательно, какой сезон. Тогда просто есть метод, который возвращает карту, где ключ-это буква группы. Что-то вроде:

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

Затем на странице JSP

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

Если вам нужно показать расписания для нескольких сезонов, вы должны иметь метод в классе WateringSchedule, который возвращает карту, где сезоны являются ключами, а затем карты groupToScheduledDays являются значениями.


  Сведения об ответе

piter

03:53, 13th August, 2020

Нет никакого красивого решения. Java просто не делает такие вещи хорошо. Решение майка-это в значительной степени способ сделать это, если вы хотите, чтобы строки были индексами (ключами). Другой вариант, если настройка hash-of-hashes слишком уродлива, - это добавить строки вместе (бесстыдно украденные у Майка и измененные):

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

а потом поиск:

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

Если вы недовольны общим уродством (и я не виню вас), положите все это за вызов метода:

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


  Сведения об ответе

pumpa

02:04, 12th August, 2020

tl; dr

Используя современные языковые функции и классы Java, определите свой собственный enums для представления сезонов и групп.

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

Этот метод дает Set из DayOfWeek объектов перечисления (не просто текст!), например DayOfWeek.TUESDAY & DayOfWeek.THURSDAY .

Современный Java

Может ли кто-нибудь предложить действительно классный способ сделать это?

Да.

Современный Java имеет встроенные классы, коллекции и enums, чтобы помочь вам с этой проблемой.

Структура java.time, встроенная в Java, предлагает перечисление Month и перечисление DayOfWeek .

EnumSet и EnumMap обеспечивают реализации Set и Map , которые оптимизированы для использования с enums для быстрого выполнения в очень небольшом объеме памяти.

Вы можете определить свой собственный enums для представления вашего сезона и ваших групп (A, B и так далее). Перечисление объекта в Java является гораздо более полезным и мощным, чем видно на других языках. Если вы не знакомы, см. учебник Oracle .

Простой синтаксис определения вашего собственного enums фактически обеспечивает большую часть функциональности, необходимой для решения этого вопроса, устраняя некоторые сложные кодировки. Новый синтаксис литералов для наборов и карт в методах фабрики коллекций в Java 9 (JEP 269)делает код еще проще.

Вот полное рабочее приложение. Обратите внимание, как мало кода для алгоритмов. Определение собственного пользовательского enums делает большую часть тяжелой работы.

Одно предостережение с этим кодом приложения: он не предполагает никаких изменений в ваших бизнес-определениях, или, по крайней мере, если есть изменения, вы заботитесь только о текущих правилах, “latest is greatest”. Если ваши правила меняются с течением времени, и вам нужно представить все прошлые, настоящие и будущие версии, я бы построил совсем другое приложение, вероятно, с базой данных для хранения правил. Но это приложение здесь решает вопрос, как было задано.

Season

Представьте свой сезон как перечисление Season . Каждый объект season содержит List из Month объектов enum, которые определяют длину этого конкретного сезона. Новый синтаксис List.of, добавленный к Java 9, определяет неизменяемый список в синтаксисе литералов с помощью статических методов фабрики.

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

Представьте каждую группу клиентов lawns/yards, (A, B, C, D, E) в виде перечисления с именем Group . Каждый из этих объектов перечисления содержит Map, сопоставляя объект перечисления Season с Set объектов перечисления DayOfWeek . Например, Group.A в Season.SPRING позволяет поливать на два дня, 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

Соберите все это вместе в этом классе Schedule .

Этот класс использует два enums, определенных выше, чтобы получить полезную работу. Единственный метод, реализованный до сих пор, говорит вам, какие дни недели разрешены для определенной группы на определенную дату. Метод определяет, какой Season применяется для этой даты.

Запустите метод main здесь, чтобы сбросить содержимое наших двух enums и сообщить о днях недели, позволяющих поливать в каждой группе для определенной жестко заданной даты.

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

Приставка

При запуске Schedule.main мы видим, что это сбрасывается на консоль.

Сезон: SPRING = [MARCH, APRIL]

Сезон: SUMMER = [MAY, JUNE, JULY, AUGUST]

Сезон: FALL = [SEPTEMBER, OCTOBER]

Сезон: WINTER = [NOVEMBER, DECEMBER, JANUARY, FEBRUARY]

Группа: А = {SPRING=[TUESDAY, THURSDAY], FALL=[TUESDAY, THURSDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[TUESDAY]}

Группа: B = {SPRING=[FRIDAY], FALL=[TUESDAY, FRIDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[FRIDAY]}

Группа: C = {SPRING=[MONDAY], FALL=[MONDAY, TUESDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[MONDAY]}

Группа: D = {SPRING=[WEDNESDAY, FRIDAY], FALL=[FRIDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[WEDNESDAY]}

Группа: E = {SPRING=[TUESDAY], FALL=[TUESDAY, WEDNESDAY], SUMMER=[MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY], WINTER=[WEDNESDAY]}

Группа А-дни полива на 2018-01-30 неделе # 2018-W05 это: [TUESDAY]

Группа B-дни полива на 2018-01-30 неделе # 2018-W05 это: [FRIDAY]

Группа C-дни полива на 2018-01-30 неделе # 2018-W05 это: [MONDAY]

Группа D-дни полива на 2018-01-30 неделе # 2018-W05 это: [WEDNESDAY]

Группа E-дни полива на 2018-01-30 неделе # 2018-W05 это: [WEDNESDAY]

ISO 8601 неделя

Возможно, Вам будет полезно узнать о стандарте ISO 8601 для определения недели . Стандарт придает особое значение “week” и определяет текстовый формат для представления конкретной недели или конкретного дня в пределах этой недели.

Для работы с такими неделями в пределах Java рассмотрите возможность добавления библиотеки ThreeTen-Extra в проект, чтобы использовать класс YearWeek.

LocalDate

Класс LocalDate представляет значение только для даты без time-of-day и без часового пояса.

Часовой пояс имеет решающее значение для определения даты. Для любого данного момента дата варьируется по всему миру в зависимости от зоны. Например, через несколько минут после полуночи в Париже Франция -это новый день, в то время как все еще “yesterday” в Монреале Квебек .

Если часовой пояс не указан, то JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент, поэтому ваши результаты могут отличаться. Лучше указать желаемый/ожидаемый часовой пояс явно в качестве аргумента.

Укажите правильное имя часового пояса в формате continent/region, например America/Montreal , Africa/Casablanca или Pacific/Auckland . Никогда не используйте буквенную аббревиатуру 3-4, такую как EST или IST , поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны(!).

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

Если вы хотите использовать текущий часовой пояс по умолчанию JVM, попросите его и передайте в качестве аргумента. Если этот параметр опущен, то текущее значение по умолчанию JVM применяется неявно. Лучше быть откровенным.

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

Или укажите дату. Вы можете установить месяц по номеру, с нормальной нумерацией 1-12 для января-декабря.

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.

Или, лучше, используйте заранее определенные объекты перечисления Month , по одному для каждого месяца года. Совет: Используйте эти объекты Month во всей базе кода, а не просто целое число, чтобы сделать ваш код более самодокументированным, обеспечить допустимые значения и обеспечить безопасность типов .

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

Неизменяемые коллекции

Списки, наборы и карты, рассмотренные выше, в идеале должны быть неизменяемыми коллекциями, поскольку изменение членства в этих коллекциях, вероятно, будет путаницей и ошибкой.

Новый синтаксис Java 9 List.of и Map.of уже обещают быть неизменными. Однако в нашем случае Map в идеале должен быть EnumMap для эффективности производительности и памяти. Текущая реализация Map.of и Set.of , по-видимому, не обнаруживает использование enums в качестве членов и автоматически оптимизируется с внутренним использованием EnumMap и EnumSet . Существует проблема OpenJDK, открытая для рассмотрения таких проблем: рассмотрите усовершенствования EnumMap и EnumSet .

Один из способов получить неизменяемый EnumSet и неизменяемый EnumMap - через библиотеку Google Guava :

Результаты каждого из них используют базовый _86 / EnumMap . Такие операции, как get и put , вызывают исключение. Таким образом, вы получаете связанные с перечислением оптимизации вместе с неизменяемостью.

Вот классы Season и Group , рассмотренные выше, модифицированные для использования библиотеки Google Guava 23.6.

Season с неизменностью

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 с неизменностью

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

}

О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют старые устаревшие классы даты и времени , такие как java.util.Date , Calendar , & SimpleDateFormat .

Проект Joda-Time , теперь находящийся в режиме обслуживания, рекомендует перейти на классы java.time.

Дополнительные сведения см. В руководстве Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Где получить классы java.time?

  • Java SE 8 , Java SE 9 и позже
    • Встроенный.
    • Часть стандарта Java API с комплектной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time обратно портирована на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализаций Android bundle классов java.time.
    • Для более раннего Android проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите, как использовать ThreeTenABP... .

В ThreeTen-дополнительный проект расширяет java.time с дополнительных занятий. Этот проект является испытательным полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы , такие как Interval , YearWeek , YearQuarter и другие .


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться