9

Вопрос по date-parsing, parsing, date, java – Самый быстрый способ анализа даты YYYYMMdd в Java [закрыто]

При разборе даты ГГГГММдд, например, 20120405 от 5 апреля 2012 года, какой метод самый быстрый?

int year = Integer.parseInt(dateString.substring(0, 4));
int month = Integer.parseInt(dateString.substring(4, 6));
int day = Integer.parseInt(dateString.substring(6));

против

int date = Integer.parseInt(dateString)
year = date / 10000;
month = (date % 10000) / 100; 
day = date % 100;

мод 10000 для месяца будет, потому что мод 10000 приводит к MMdd, а результат / 100 равен MM

В первом примере мы выполняем 3 строковые операции и 3 "разбираем на int", во втором примере мы делаем много вещей по модулю.

Что быстрее? Есть ли еще более быстрый метод?

  • +1 - за то, что указал на то, что ОП, вероятно, тратит время на поиски самого быстрого решения.

    от
  • Почти во всех нормальных ситуациях я бы предпочел решение по модулю, опубликованное OP, даже если это быстрее. Зачем? Потому что вы понимаете, что происходит за несколько секунд, когда видите этот код. Ваш код немного умнее, но, следовательно, требует больше времени для понимания, что является недостатком. И я сомневаюсь, что во многих случаях преобразование даты является узким местом в производительности.

    от
  • @Alderath Полностью согласен - я никогда не включу то, что я написал в своем коде! Но это действительно отвечает на вопрос!

    от
  • Не обращайте внимания на мой комментарий, я не вижу корректировкиyearZero так далее..

    от
  • @nim не уверен, что вы имеете в виду - 2012 год после расчета.

    от
  • +1 - для указания на недостатки в подходе OP. Я просто надеюсь, что ОП понимает ...

    от
  • Я знаю, что это старый, но я исправил вопрос, чтобы избежать путаницы.

    от user3001
  • Я понимаю :)

    от user3001
  • @DilumRanatunga Я полагаю, что есть способы взять подстроку, которая разделяет основной массив. Многие языки этого не делают (по крайней мере, не по умолчанию), потому что это может привести к утечкам, но оно идеально подходит для таких случаев использования, как этот.

    от user395760
  • Диллум, создающий подстроку в Java, является O (1) (по крайней мере, в реализации Sun) и не требует копирования. Но это лучше сделать с парсером фактической даты. Код не будет проблемой производительности в любом случае (по крайней мере, маловероятно).

    от Joey
  • Почему вы не можете написать свой собственный микро-тест и посмотреть, какой из них быстрее?

    от maerics
  • @ user3001 Из любопытства, когда ты нашел это слишком медленно? Это не самый лучший разработанный API (занижение), но я использовал его годами без проблем с производительностью.

    от
  • Это путь, синтаксический анализ строки даты должен требовать оптимизации производительности, если только вы не определили, что вы делаете это, как & gt; 10 миллионов раз в цикле для каждого запроса или некоторого такого ... (В этом случае вы должно удивляться почему).

    от
  • +1 за правильный способ сделать это.

    от
  • Это классический пример знания ваших инструментов.

    от
  • API дат Java часто слишком медленный.

    от user3001
  • Я полагаю, что по модулю математика будет гораздо быстрее, чем выделение трех (под) строк ...

    от Dilum Ranatunga
  • Почему бы вам просто не измерить это самостоятельно?

    от BalusC
6 ответов
  • 32

    Code:

    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
    Date date = format.parse("20120405");
    

  • 3

    Как насчет (но это будет разбор недействительной даты

    ничего не сказав ...):

    public static void main(String[] args) throws Exception {
        char zero = '0';
        int yearZero = zero * 1111;
        int monthAndDayZero = zero * 11;
        String s = "20120405";
        int year = s.charAt(0) * 1000 + s.charAt(1) * 100 + s.charAt(2) * 10 + s.charAt(3) - yearZero;
        int month = s.charAt(4) * 10 + s.charAt(5) - monthAndDayZero;
        int day = s.charAt(6) * 10 + s.charAt(7) - monthAndDayZero;
    }
    

    Проведя быстрый и грязный тест с 100 000 прогонов и 10 000 000 синхронизированных итераций, я получаю:

    700ms for your first method 350ms for your second method 10ms with my method.

  • 3

    Второй наверняка будет быстрее, как только вы поменяете

    mod в% и добавить пропущенные точки с запятой и исправить делитель вyear расчет. Тем не менее, мне трудно представить приложение, где это является узким местом. Сколько раз вы анализируетеYYYYMMdd даты в их компонентах, без необходимости их проверки?

  • 5

    Я провел быстрый тест

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

    t.startTiming();
    for(int i=0;i<1000000;i++) {
        int year = Integer.parseInt(dateString.substring(0, 4));
        int month = Integer.parseInt(dateString.substring(4, 6));
        int day = Integer.parseInt(dateString.substring(6));
    }
    t.stopTiming();
    System.out.println("First method: "+t.getElapsedTime());
    
    Time t2 = new Time();
    t2.startTiming();
    for(int i=0;i<1000000;i++) {
        int date = Integer.parseInt(dateString);
        int y2 = date / 1000;
        int m2 = (date % 1000) / 100;
        int d2 = date % 10000;
    }
    t2.stopTiming();
    System.out.println("Second method: "+t2.getElapsedTime());
    

    Результаты не лгут (в мс).

    First method: 129
    Second method: 53
    

  • 0

    Я считаю

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

    Мод является стандартным математическим оператором и, вероятно, очень оптимизирован.

    Но, как сказал Хантер МакМиллен: «Вы должны взглянуть на API класса Calendar».

  • 14

    Как вы видите ниже

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

    Хотя вы могли бы использоватьSimpleDateFormat, это не реентерабельное, поэтому следует избегать. Лучшее решение - использовать классы времени Joda:

    private static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
         .appendYear(4,4).appendMonthOfYear(2).appendDayOfMonth(2).toFormatter();
    ...
    Date date = DATE_FORMATTER.parseDateTime(dateOfBirth).toDate();
    

    Если мы говорим о ваших математических функциях, первое, на что следует обратить внимание, - это то, что в вашем математическом коде были ошибки, которые я исправил.That's проблема с выполнением вручную. Тем не менее, те, которые обрабатывают строку один раз, будут самыми быстрыми. Быстрый тестовый запуск показывает, что:

    year = Integer.parseInt(dateString.substring(0, 4));
    month = Integer.parseInt(dateString.substring(4, 6));
    day = Integer.parseInt(dateString.substring(6));
    

    Принимает ~ 800 мс:

    int date = Integer.parseInt(dateString);
    year = date / 10000;
    month = (date % 10000) / 100; 
    day = date % 100;
    total += year + month + day;
    

    Занимает ~ 400 мс.

    However ... again... Вы должны принять во внимание, что это после10 million итераций. Это прекрасный пример преждевременной оптимизации. Я бы выбрал тот, который наиболее читабелен и прост в обслуживании. Вот почему ответ времени Joda является лучшим.