Как определить, является ли символ буквой в Java?

Как проверить, является ли односимвольная строка буквой, включая буквы с диакритическими знаками?

Мне недавно пришлось разобраться с этим, поэтому я сам отвечу на него после того, как мне напомнил недавний вопрос о VB6.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
27
0
46 842
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Просто проверяю, находится ли буква от A до Z, потому что она не включает буквы с надстрочными знаками или буквы других алфавитов.

Я обнаружил, что вы можете использовать класс регулярных выражений для 'буквы Unicode' или одну из его вариаций с учетом регистра:

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

Вы также можете сделать это с помощью класса Характер:

Character.isLetter(character);

но это менее удобно, если вам нужно проверить более одной буквы.

Character.isLetter () намного быстрее, чем string.matches (), потому что string.matches () каждый раз компилирует новый Pattern. Я думаю, что даже кеширование шаблона будет лучше.


Обновлено: Просто наткнулся на это снова и подумал, что попробую найти реальные цифры. Вот моя попытка провести тест, проверяя все три метода (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));
    }
}

И мой вывод:

10000000 tests of Pattern.matches() took 4325146672 ns.
There were 4062500/10000000 valid characters
10000000 tests of isLetter() took 546031201 ns.
There were 4062500/10000000 valid characters
10000000 tests of String.matches() took 11900205444 ns.
There were 4062500/10000000 valid characters

Так что это почти в 8 раз лучше, даже с кешированным Pattern. (А без кеширования почти в 3 раза хуже, чем кешированный.)

Вы должны использовать c.codePointAt(0), а не c.charAt(0) в testCharacter(); в противном случае это не удастся для символов вне BMP.

Mechanical snail 20.03.2012 05:01

Другие вопросы по теме