Вместо нескольких операторов if дата Java - PullRequest
0 голосов
/ 26 июня 2018

Есть ли лучший способ написать это вместо записи нескольких операторов if?

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

public class OrganisingData {

    static int jan16=0;
    static int feb16=0;
    static int mar16=0;//... static int dec18

    public static void Months(String dates) {
        if (dates.substring(2, 4).equals("16") && 
            dates.substring(5,7).equals("01")) {
            jan16++;
        }
        if (dates.substring(2, 4).equals("16") && 
            dates.substring(5,7).equals("02")) {
            feb16++;...
        }
        if (dates.substring(2, 4).equals("18") &&
            dates.substring(5,7).equals("12")) {
            dec18++;
        }
    }
}

Я пытаюсь построить гистограмму, и jan16 feb16 и т. Д. Представляют месяц и год, и каждый раз, когда я настаиваю на настаивании на этой дате (например, 2016-01-15), я буду увеличивать jan16,поэтому вместо написания нескольких операторов if для каждого месяца + года (всего 32 оператора if), есть ли лучший способ написать это?

Ответы [ 5 ]

0 голосов
/ 26 июня 2018

YearMonth

Видимо, вы хотите отслеживать значения год-месяц.Для этого есть класс, названный, ну, YearMonth.Найдите этот класс в пакете java.time , который вытеснит ужасно хлопотные старые классы даты и времени, включенные в самые ранние версии Java.

MonthDay

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

Month

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

LocalDate

Если входные строки представляют год и месяц идень месяца, разобрать как LocalDate.У этого класса нет времени суток и часового пояса.

LocalDate ld = LocalDate.parse( "2016-01-15" ) ;

Извлечение YearMonth, MonthDay или Month.

YearMonth ym = YearMonth.from( ld ) ;

Создание коллекции,Возможно, вы хотите сохранить все отдельные наборы LocalDate объектов в конкретный год-месяц.Если это так, создайте Map, где каждому YearMonth объекту принадлежит Set из LocalDate объектов.

Map < YearMonth, Set < LocalDate > > map = new HashMap <>();

При обработке каждой входной даты проверьте, есть ли на карте Set еще создано для конкретного YearMonth ввода.Если нет, создайте экземпляр TreeSet.Класс TreeSet - это SortedSet, то есть он поддерживает отсортированный порядок при добавлении значений.

Set < LocalDate > set = map.get( ym );
if ( null == set ) {
    set = new TreeSet <>(); // A `TreeSet` is a `SortedSet`, maintains a sorted order. You may or may not need this behavior.
    map.put( ym , set );
}

Имея Set в руке, добавьте LocalDate.

set.add( ld );

После обработки вы можете получить набор ключей YearMonth из вашего Map.И для каждого из них вы можете получить Set, которым он владеет, и получить количество содержащихся в нем элементов.

Lamba & Streams

Для более короткого кода вы можете использовать синтаксис Lambda & Streams с Map::computeIfAbsent.Я видел такой код, но еще не пробовал.

map.computeIfAbsent( key , k -> new TreeSet< LocalDate >() ).add( ld ) ;

Только счетчик

Если вам нужен только счетчик, и вам не нужны значения LocalDateзамените Set как «значение» или вы Map на Integer объект.Вместо извлечения Set и добавления к нему, извлеките Integer и увеличьте его, добавив единицу.Лично в такой ситуации лучше всего собрать значения LocalDate, которые будут проверены для отладки / тестирования и / или для дальнейшего использования в другой бизнес-логике.


О java.time

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

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

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

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

  • Java SE 8 , Java SE 9 , Java SE 10, а позже
    • Встроенный.
    • Часть стандартного Java API с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android связывают реализации классов java.time.
    • Для более ранней версии Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянутое выше).См. Как использовать ThreeTenABP… .

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

0 голосов
/ 26 июня 2018

По сути, это сочетание слов @John T и @Zachary, но с правильным синтаксисом и преобразованием типов.

// [Years] and [Months], where [0][0] is jan 2000. May need to adjust for previous years.
int[][] days = new int[30][12];

void month(String dates) {
    int year = Integer.parseInt(dates.substring(2, 4)); 
    int month = Integer.parseInt(dates.substring(5,7)) - 1;

    days[year][month]++;
}
0 голосов
/ 26 июня 2018

Просмотрите ваш документ с помощью:

// 18 years(more needed?), 12 months
String[][] yearsAndMonths = new String[18][12];  

yearsAndMonths[dates.substring(5,7)][dates.substring(2, 4)]++;

Затем распечатайте результаты.

Я не эксперт по Java.Код только что предоставил вам логику.

0 голосов
/ 26 июня 2018

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

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

import java.util.Map;
import java.util.HashMap;

private static Map<Integer, int[]> years = new HashMap<>();
private static String[] monthNames = new String[] {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

static {
    for(int year = 16; year <= 18; year++) {
        years.put(year, new int[12]);
    }
}

public static void months(String dates) { // method names should start with lower case
    int year = Integer.parseInt(dates.substring(2, 4));
    int month = Integer.parseInt(dates.substring(5, 7)) - 1; // date String is one-based, array-index is zero-based
    years.get(year)[month]++;
}

public static void print() {
    for(int year = 16; year <= 18; year++) {
        int[] monthCounts = years.get(year);
        for(int month = 0; month < 12; month++) {
            System.out.println(monthNames[month] + " " + year + ": " + monthCounts[month]);
        }
    }
}

Вы можете увидеть код в действии здесь .

0 голосов
/ 26 июня 2018

Вы можете использовать оператор switch , чтобы уменьшить неуклюжую логику, хотя это не обязательно будет сильно сокращаться.Вам нужно будет либо использовать Strings с Switch , либо преобразовать значения дня / месяца в целое число.

String day = dates.substring(2, 4);
String month = dates.substring(5, 7);

switch (month) {
    case "01" : {
        if (day.equals("16"))
            jan16++;
        break;
    }
}

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

int count[] = new int[12];
  ...
int day = Integer.parseInt(dates.substring(2, 4));
int month = Integer.parseInt(dates.substring(5, 7));


if (day == 16)
    count[month - 1]++;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...