27

1 文字の文字列が文字であるかどうか (アクセント付きの文字を含む) を確認するにはどうすればよいですか?

最近これを解決しなければならなかったので、最近のVB6の質問で思い出したので、自分で答えます。

4

2 に答える 2

33

string.matches()は毎回新しいパターンをコンパイルするため、Character.isLetter()はstring.matches()よりもはるかに高速です。パターンをキャッシュしても、isLetter()はそれを打ち負かすと思います。


編集:ちょうどこれに再び遭遇し、私がいくつかの実際の数を考え出そうと思った。これがベンチマークでの私の試みであり、3つの方法すべてをチェックします(matches()、、およびをキャッシュするPattern場合としない場合Character.isLetter())。また、物事を歪めないように、有効な文字と無効な文字の両方がチェックされていることを確認しました。

import java.util.regex.*;

class TestLetter {
    private static final Pattern ONE_CHAR_PATTERN = Pattern.compile("\\p{L}");
    private static final int NUM_TESTS = 10000000;

    public static void main(String[] args) {
        long start = System.nanoTime();
        int counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testMatches(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of Pattern.matches() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
        /*********************************/
        start = System.nanoTime();
        counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testCharacter(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of isLetter() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
        /*********************************/
        start = System.nanoTime();
        counter = 0;
        for (int i = 0; i < NUM_TESTS; i++) {
            if (testMatchesNoCache(Character.toString((char) (i % 128))))
                counter++;
        }
        System.out.println(NUM_TESTS + " tests of String.matches() took " +
                (System.nanoTime()-start) + " ns.");
        System.out.println("There were " + counter + "/" + NUM_TESTS +
                " valid characters");
    }

    private static boolean testMatches(final String c) {
        return ONE_CHAR_PATTERN.matcher(c).matches();
    }
    private static boolean testMatchesNoCache(final String c) {
        return c.matches("\\p{L}");
    }
    private static boolean testCharacter(final String c) {
        return Character.isLetter(c.charAt(0));
    }
}

そして私の出力:

Pattern.matches()の10000000テストには4325146672nsかかりました。
4062500/10000000の有効な文字がありました
isLetter()の10000000テストには546031201nsかかりました。
4062500/10000000の有効な文字がありました
String.matches()の10000000テストには11900205444nsかかりました。
4062500/10000000の有効な文字がありました

つまり、キャッシュされている場合でも、ほぼ8倍優れていPatternます。(そして、キャッシュされていないものは、キャッシュされているものよりもほぼ3倍悪いです。)

于 2008-09-18T16:10:41.373 に答える
22

アクセント付きの文字や他のアルファベットの文字が含まれていないため、文字が AZ にあるかどうかを確認するだけです。

「Unicode 文字」の正規表現クラス、または大文字と小文字を区別するバリエーションの 1 つを使用できることがわかりました。

string.matches("\\p{L}"); // Unicode letter
string.matches("\\p{Lu}"); // Unicode upper-case letter

Characterクラスでこれを行うこともできます。

Character.isLetter(character);

ただし、複数の文字をチェックする必要がある場合は不便です。

于 2008-09-18T16:08:06.933 に答える