10

YYYYMMddの日付を解析する場合、たとえば2012年4月5日の20120405の場合、最速の方法は何ですか?

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;

月のmod10000は、mod 10000の結果がMMddになり、結果/100がMMになるためです。

最初の例では、3つの文字列演算と3つの "parse to int"を実行し、2番目の例では、モジュロを介して多くのことを実行します。

何が速いですか?さらに速い方法はありますか?

4

6 に答える 6

33
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
Date date = format.parse("20120405");
于 2012-04-04T15:15:14.627 に答える
14

以下に示すように、日付処理のパフォーマンスは、何百万もの反復を見る場合にのみ関係します。代わりに、読みやすく、保守しやすいソリューションを選択する必要があります。

を使用することはできますが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();

私たちがあなたの数学関数について話している場合、最初に指摘することは、私が修正したあなたの数学コードにバグがあったということです。それが手作業の問題です。とはいえ、文字列を1回処理するものが最速になります。簡単なテスト実行は次のことを示しています。

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;

約400msかかります。

ただし...繰り返しますが...これは1,000万回の反復後であることを考慮する必要があります。これは時期尚早の最適化の完璧な例です。最も読みやすく、保守が最も簡単なものを選択します。だからこそ、城田時間の答えが一番です。

于 2012-04-04T15:21:06.937 に答える
5

両方のメソッドをそれぞれ100万回実行する簡単なベンチマークテストを行いました。結果は、Dilum Ranatungaが予測したように、モジュロ法がはるかに高速であることを明確に示しています。

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
于 2012-04-04T15:24:06.160 に答える
3

不足しているセミコロンに変更modして追加し、計算で除数を修正すると、2番目の方が確実に高速になります。とはいえ、これがボトルネックになっているアプリケーションを想像するのは難しいと思います。日付を検証する必要なしに、日付をコンポーネントに解析するのは何回ですか?%yearYYYYMMdd

于 2012-04-04T15:14:10.687 に答える
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
  • 2番目の方法は350ms
  • 私の方法で10ms。
于 2012-04-04T15:15:21.277 に答える
0

modメソッドの方が速いと思います。関数を呼び出すことにより、スタック上に変数と場所のインスタンスを作成し、より重いソリューションを作成します。

Modは標準の数学演算子であり、非常に最適化されている可能性があります。

しかし、Hunter McMillenが言ったように、「CalendarクラスAPIを確認する必要があります」

于 2012-04-04T15:14:35.973 に答える