Подтвердить что ты не робот

Самый быстрый способ проверки строки - буквенно-цифровой в Java

Каков самый быстрый способ проверить, что строка содержит только буквенно-цифровые символы.

У меня есть код, который собирается пережевывать много CPU, и мне интересно, будет ли он быстрее, чем использовать предварительно скомпилированные регулярные выражения.

ОБНОВЛЕНИЕ:. Так много голосов, нужно объяснить? Stackoverflow не следует использовать для обсуждения того, какой алгоритм использовать для достижения задачи может быть быстрее?

4b9b3361

Ответ 1

Я написал тесты, которые проверяют использование регулярных выражений (как и в других ответах) на предмет отсутствия регулярных выражений. Тесты выполнены на четырехъядерном компьютере с OSX10.8 под управлением Java 1.6

Интересно, что использование регулярных выражений оказывается примерно в 5-10 раз медленнее, чем ручная итерация по строке. Кроме того, isAlphanumeric2() несколько быстрее, чем isAlphanumeric().

public class QuickTest extends TestCase {

    private final int reps = 1000000;

    public void testRegexp() {
        for(int i = 0; i < reps; i++)
            ("ab4r3rgf"+i).matches("[a-zA-Z0-9]");
    }

public void testIsAlphanumeric() {
    for(int i = 0; i < reps; i++)
        isAlphanumeric("ab4r3rgf"+i);
}

public void testIsAlphanumeric2() {
    for(int i = 0; i < reps; i++)
        isAlphanumeric2("ab4r3rgf"+i);
}

    public boolean isAlphanumeric(String str) {
        for (int i=0; i<str.length(); i++) {
            char c = str.charAt(i);
            if (!Character.isDigit(c) && !Character.isLetter(c))
                return false;
        }

        return true;
    }

    public boolean isAlphanumeric2(String str) {
        for (int i=0; i<str.length(); i++) {
            char c = str.charAt(i);
            if (c < 0x30 || (c >= 0x3a && c <= 0x40) || (c > 0x5a && c <= 0x60) || c > 0x7a)
                return false;
        }
        return true;
    }

}

Ответ 2

Используйте String.matches(), например:

String myString = "qwerty123456";
System.out.println(myString.matches("[A-Za-z0-9]+"));

Это не может быть абсолютным "самым быстрым" возможным подходом. Но в целом не так много смысла пытаться конкурировать с людьми, которые пишут "стандартную библиотеку" в плане производительности.

Ответ 3

Регулярное выражение, вероятно, будет довольно эффективным, потому что вы должны указывать диапазоны: [0-9a-zA-Z]. Предполагая, что код реализации для регулярных выражений эффективен, для этого просто потребовалось бы сравнение сверху и снизу для каждого диапазона. Здесь в основном то, что должно выполняться скомпилированным регулярным выражением:

boolean isAlphanumeric(String str) {
    for (int i=0; i<str.length(); i++) {
        char c = str.charAt(i);
        if (c < 0x30 || (c >= 0x3a && c <= 0x40) || (c > 0x5a && c <= 0x60) || c > 0x7a)
            return false;
    }

    return true;
}

Я не вижу, как ваш код мог бы быть более эффективным, чем это, потому что каждый символ должен быть проверен, а сравнения не могут быть действительно проще.