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

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

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

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

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

Если я нахожусь в группе А, вот мои разрешенные времена: зима: только по понедельникам весна: вторник, четверг, суббота лето: любой день осень: вторник, четверг, суббота

Если бы я писал это на 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';

Я мог бы сделать массивы дней (массив («вторник», «четверг», «суббота»)) и т. Д., Но это не обязательно для того, что я действительно пытаюсь выполнить.

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

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

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

15.08.2008 23:07:03
12 ОТВЕТОВ
РЕШЕНИЕ

Вы можете сделать, по сути, тот же код с Hashtables (или другой картой):

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 не является динамическим языком и не имеет хешей на уровне языка.

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

10
15.08.2008 23:16:52
Используйте HashMap вместо Hashtable для лучшей производительности. Hashtable, как Vector, ДЕЙСТВИТЕЛЬНО старый и не должен использоваться из соображений производительности. Главным образом, потому что все синхронизировано, когда это не должно быть.
MetroidFan2002 16.09.2008 03:04:29

Там нет красивого решения. 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 */ }
0
15.08.2008 23:27:13

Я не программист на 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";
3
15.08.2008 23:59:53

Не пытайтесь быть таким же динамичным, как 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 перед ее использованием. Этот класс синхронизирован, что означает, что каждый вызов защищен от многопоточности, что действительно замедляет доступ, когда вам не нужна дополнительная защита. Пожалуйста, используйте любую реализацию Map вместо HashMap или TreeMap .

9
16.08.2008 00:21:05
+1 Я думаю, что имя интерфейса Пользователь должен переименовать в UserGroup для ясности.
zawhtut 6.01.2011 15:51:57

Кажется, что каждый пытается найти способ 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);
...

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

6
16.08.2008 00:28:34

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

public String lookupDays(String group, String date);

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

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

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

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

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

}

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

1
16.08.2008 00:53:11

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

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

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

2
16.08.2008 01:07:35

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

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

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

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

1
3.11.2017 00:47:10

Должна ли «дата» быть параметром? Если вы просто показываете текущее расписание полива, класс 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, который возвращает карту, где Seasons - это ключи, а затем Maps of groupToScheduledDays - значения.

1
16.08.2008 04:35:49

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

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 );
4
16.08.2008 07:37:11

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

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

}

РЕДАКТИРОВАТЬ: Кроме того, ваши диапазоны дат не учитывают високосные годы:

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

2
16.08.2008 12:09:44

ТЛ; др

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

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

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

Современная Ява

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

Да.

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

Платформа java.time, встроенная в Java, предлагает Monthперечисления и DayOfWeekперечисления.

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

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

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

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

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

Season

Представьте свой сезон как перечисление Season. Каждый объект сезона проводит Listиз Monthперечисляемых объектов , которые определяют длину этого конкретного сезона. Новый 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

Представьте каждую группу газонов / дворов клиентов (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классе.

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

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

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мы видим это сбрасывается в консоль.

Сезон: ВЕСНА = [МАРТ, АПРЕЛЬ]

Сезон: ЛЕТО = [МАЙ, ИЮНЬ, ИЮЛЬ, АВГУСТ]

Сезон: ОСЕНЬ = [СЕНТЯБРЬ, ОКТЯБРЬ]

Сезон: ЗИМА = [НОЯБРЬ, ДЕКАБРЬ, ЯНВАРЬ, ФЕВРАЛЬ]

Группа: A = {ВЕСНА = [ВТОРНИК, ЧЕТВЕРГ], FALL = [ВТОРНИК, ЧЕТВЕРГ], ЛЕТО = = ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, четверг, пятница, суббота, воскресенье], ЗИМА = [ВТОРНИК]}

Группа: B = {SPRING = [ПЯТНИЦА], FALL = [ВТОРНИК, ПЯТНИЦА], ЛЕТО = = ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, ПЯТНИЦА, СУББОТА, ВОСКРЕСЕНЬ], ЗИМА = [ПЯТНИЦА]}

Группа: C = {SPRING = [ПОНЕДЕЛЬНИК], FALL = [ПОНЕДЕЛЬНИК, ВТОРНИК], ЛЕТО = = ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, ПЯТНИЦА, СУББОТА, Воскресенье], ЗИМА = [ПОНЕДЕЛЬНИК]}

Группа: D = {SPRING = [СРЕДА, ПЯТНИЦА], FALL = [ПЯТНИЦА], ЛЕТО = = ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, ПЯТНИЦА, СУББОТА, ВОСКРЕСЕНЬ], ЗИМА = [СРЕДА]]

Группа: E = {SPRING = [ВТОРНИК], FALL = [ВТОРНИК, СРЕДА], ЛЕТО = = ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, пятница, суббота, воскресенье], ЗИМА = [СРЕДА]}

Группа A - дни полива на 2018-01-30 неделе # 2018-W05: [ВТОРНИК]

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

Группа C - дни полива на 2018-01-30 неделе # 2018-W05: [ПОНЕДЕЛЬНИК]

Группа D - Дни полива на 2018-01-30 неделе # 2018-W05: [СРЕДА]

Группа E - дни полива на 2018-01-30 неделе # 2018-W05: [СРЕДА]

ISO 8601 неделя

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

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

LocalDate

LocalDateКласс представляет собой дату только значение без времени суток и без временной зоны.

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

Если часовой пояс не указан, 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предварительно определенные объекты enum, по одному на каждый месяц года. Совет: используйте эти Monthобъекты по всей вашей кодовой базе, а не просто как целое число, чтобы сделать ваш код более самодокументированным, обеспечить допустимые значения и обеспечить безопасность типов .

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

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

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

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

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

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

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

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
0
30.01.2018 07:09:29