Есть ли более быстрый метод для соответствия произвольной строке к имени месяца в Java

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

boolean isaMonth( String str ) {
    String[] months = DateFormatSymbols.getInstance().getMonths();
    String[] shortMonths = DateFormatSymbols.getInstance().getShortMonths();
    int i;

    for( i = 0; i<months.length(); ++i;) {
        if( months[i].equals(str) ) return true;
        if( shortMonths[i].equals(str ) return true;
    }
    return false;
}

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

Я видел другой вопрос, который говорил о Regex для соответствия имени месяца и год, который мог быть адаптирован к этой ситуации. Regex был бы быстрее? Есть ли какое-либо другое решение, которое могло бы быть быстрее?

5
задан jonc 21 May 2010 в 03:44
поделиться

3 ответа

Почему бы не сохранить названия месяцев в HashSet ? Это даст вам постоянный поиск по времени вместо линейного поиска по времени, который вы получаете из своего цикла.

import java.util.HashSet;
import java.util.Collections;
import java.text.DateFormatSymbols;

class Test {
  public static void main(String[] args) {

    HashSet<String> months = new HashSet<String>(24);  

    Collections.addAll(months, DateFormatSymbols.getInstance().getMonths());
    Collections.addAll(months, DateFormatSymbols.getInstance().getShortMonths());

    System.out.println(months.contains(args[0]));

  }
}
3
ответ дан 14 December 2019 в 19:04
поделиться

Объедините месяцы и shortMonths в один отсортированный массив и выполните двоичный поиск в этом массиве. Или объедините их в набор (HashSet) и используйте contains. Измените все названия месяцев на строчные и сделайте то же самое со значением поиска, если вы хотите, чтобы регистр не учитывался.

Если вы хотите получить номер месяца, объедините их все в карту (HashMap) со значением, являющимся номером месяца.

1
ответ дан 14 December 2019 в 19:04
поделиться

HashSet - хорошее решение общего назначения - но я думаю, что вы можете сделать лучше. Посмотрите на первую букву месяца - jfmasond - если вы предварительно отфильтруете их и проведете проверку HashSet только в том случае, если она пройдет, это решит огромное количество ваших сценариев "return false".

Вы можете настроить это несколькими способами - один из самых простых способов - использовать оператор switch, хотя таблица поиска была бы быстрее. Заметим также, что проверка нужна только в том случае, если первый символ находится между a и s, поэтому в таблице поиска не обязательно использовать весь код Юникода (или UTF-8, в зависимости от требований).

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

PS - прежде чем делать что-либо из этого, вам следует провести профилирование и убедиться, что именно эта область вашего кода является узким местом.

1
ответ дан 14 December 2019 в 19:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: