5

文字列が月の名前であるかどうかを判断したいのですが、比較的迅速に実行したいと考えています。現在私の脳に詰まっている機能は次のようなものです。

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

ただし、大量のテキストを処理し、一度に 1 つの文字列をこの関数に渡します。ほとんどの場合、ループ全体を通過して false を返すという最悪のケースになります。

この状況に適応できる月名と年に一致する正規表現について話している別の質問を見ました。正規表現の方が速いでしょうか? もっと速いかもしれない他の解決策はありますか?

4

3 に答える 3

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

  }
}
于 2010-05-21T03:52:11.483 に答える
1

HashSetは優れた汎用ソリューションですが、もっとうまくできると思います。月の最初の文字であるjfmasondを見てください。これらを事前にフィルタリングし、合格した場合にのみHashSetチェックを実行すると、膨大な数の「falseを返す」シナリオが処理されます。

これはいくつかの方法で設定できます。非常に簡単な方法の1つは、switchステートメントを使用することですが、ルックアップテーブルの方が高速です。また、最初の文字がaとsの間にあるかどうかをチェックするだけでよいので、ルックアップテーブルに完全なUnicode(または要件によってはUTF-8)コードスペースが必要ないことにも注意してください。

これをさらに効果的にするために、毎月の最初の2文字が含まれるようにルックアップテーブルを作成できます。結果のルックアップテーブルは大きすぎず、これにより、チェックする必要のある単語の数が大幅に削減されます。ハッシュセット。

PS-これを行う前に、プロファイリングを行い、これが実際にボトルネックになっているコードの領域であることを確認する必要があります。

于 2010-05-21T04:21:18.153 に答える
1

month と shortMonths を 1 つの並べ替えられた配列にマージし、配列に対してバイナリ検索を実行します。または、両方をセット (HashSet) にマージして、contains を使用します。大文字と小文字を区別しない場合は、すべての月の名前を小文字に変更し、検索値でも同じことを行います。

月の番号を取得できるようにする場合は、それらをすべてマップ (HashMap) にマージし、値を月番号にします。

于 2010-05-21T04:02:49.347 に答える