如何检查一个只有一个字符的字符串是否是字母,包括带有重音符号的任何字母?
最近我也曾需要解决这个问题,所以在最近的VB6问题提醒下,我会自己回答。
Character.isLetter()
比string.matches()
快得多,因为string.matches()
每次都要编译新的正则表达式。即使缓存了模式,我认为isLetter()
仍然能够胜过它。
编辑:再次遇到这个问题,想试着给出一些实际的数据。以下是我的基准测试,检查所有三种方法(带有和不带有缓存Pattern
的matches()
,以及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个测试耗时4325146672纳秒。 有4062500/10000000个有效字符。 isLetter()的10000000个测试耗时546031201纳秒。 有4062500/10000000个有效字符。 String.matches()的10000000个测试耗时11900205444纳秒。 有4062500/10000000个有效字符。
所以即使使用缓存的Pattern
,速度也提高了近8倍。(而未缓存的速度比缓存还慢近3倍。)
我只是想确认一个字母是否在A-Z之间,因为这并不包括带有重音符号的字母或其他字母表中的字母。
我发现可以使用正则表达式类来匹配“Unicode字母”或其区分大小写的变体之一:
string.matches("\\p{L}"); // Unicode letter
string.matches("\\p{Lu}"); // Unicode upper-case letter
您也可以使用Character类来完成此操作:Character.isLetter(character);
但是如果你需要检查多个字母,这样就不太方便了。
testCharacter()
中,你应该使用c.codePointAt(0)
而不是c.charAt(0)
;否则它将无法处理超出BMP范围的字符。 - Mechanical snail