Вопрос

Для меня это неприятный случай...Я 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';

Я МОГ бы создать массивы дней (array("Вторник", "Четверг", "Суббота")) и т.д., но это не обязательно для того, чего я действительно пытаюсь достичь.

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Не пытайтесь быть таким динамичным, как 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);
}

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

Похоже, что все пытаются найти 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 делает это так просто и так весело!

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

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

Я не программист на 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";

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

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

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

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

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)

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

public String lookupDays(String group, String date);

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

A.Лето=M
A.Пружина=tTS
B.Лето=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);
  }

}

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

Должна ли "дата" быть параметром?Если вы просто показываете текущее расписание полива, класс 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 являются значениями.

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

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

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

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

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

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 */ }

tl;dr

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

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

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

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

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

ДА.

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

Тот Самый java.время фреймворк, встроенный в Java, предлагает Month перечисление и DayOfWeek перечисление.

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

Вы можете определить свой собственный перечисления представлять свой сезон и свои группы (A, B и так далее).Средство перечисления в 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.Каждый из этих объектов enum содержит Map, отображающий Season объект enum для a 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 = {ВЕСНА=[ВТОРНИК, ЧЕТВЕРГ], ОСЕНЬ=[ВТОРНИК, ЧЕТВЕРГ], ЛЕТО=[ПОНЕДЕЛЬНИК, ВТОРНИК, СРЕДА, ЧЕТВЕРГ, ПЯТНИЦА, СУББОТА, ВОСКРЕСЕНЬЕ], ЗИМА=[ВТОРНИК]}

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

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

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

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

Группа А – Дни полива на 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 рассмотрите возможность добавления Три дня-Дополнительно библиотеку к вашему проекту, чтобы использовать YearWeek класс.

LocalDate

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

Часовой пояс имеет решающее значение при определении даты.Для любого данного момента дата варьируется по всему миру в зависимости от зоны.Например, через несколько минут после полуночи в Париж, Франция это новый день, хотя он все еще “вчерашний” в Montréal Québec.

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

Укажите a правильное название часового пояса в формате 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 библиотека:

Результаты каждого из них используют лежащий в основе EnumSet/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.время фреймворк встроен в Java 8 и более поздние версии.Эти классы вытесняют старые, вызывающие беспокойство наследие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Тот Самый Джода-Время проект, находящийся сейчас в режим технического обслуживания, рекомендует перейти на java.время классы.

Чтобы узнать больше, смотрите Учебное пособие по Oracle.И найдите в Stack Overflow множество примеров и объяснений.Спецификация такова 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-Задний порт.
  • Android
    • Более поздние версии Android содержат реализации классов java.time.
    • Для более ранних версий Android Тритенабп адаптация проекта ThreeTen-Задний порт (упоминалось выше).Видишь Как использовать ThreeTenABP….

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top