2013-10-15 5 views
2

Я пытаюсь определить, что является быстрым способа реализовать этот код:Самый быстрый способ решить, содержит ли строка только допустимые значения?

Pattern ID_REGEX = Pattern.compile("[A-Za-z0-9_\\-.]+"); 
boolean match = ID_REGEX.matcher(id).matches(); 
if (!match) throw new IllegalArgumentException("Disallowed character in ID"); 

Учитывая, что ID_REGEX постоянна, я предполагаю, что-то вроде BitSet или массива допустимых значений является самым быстрым способ реализовать это, может быть, даже просто огромную if-инструкцию.

Отметьте, что поиск осуществляется по A-Za-z, не Character.isLetter.

Дополнительная престижность для реализации ОССА

+1

Я не понимаю. Вы имеете в виду без регулярного выражения в java? – Jason

+2

Почему бы вам просто не написать тест, чтобы измерить его? –

+5

Действительно ли это * производительность критическая? Имеет ли код, который у вас уже есть, не работает быстро * достаточно *? –

ответ

3

Моего быстро, но неясно решение

// encapsulate this into a class and do once; perhaps use a static initializer 
boolean[] allowed = new boolean[256]; // default false 
allowed[32] = true; 
allowed['a'] = true; 
// fill all allowed characters 
allowed['Z'] = true; 

// the check 
for (int n=0,len=str.length(); n<len; n++) { 
    char ch = str.charAt(n); 
    if (ch>255 || !allowed[ch]) { 
    return false; 
    } 
} 
return true; 

Некоторые дополнительные броски могут быть необходимы, но я надеюсь, что идея ясна.

+0

Измените проверку 'ch> 256' на' ch> 255', чтобы избежать неприятных сюрпризов, когда ch 256. –

+0

@RogerLindsjo thx, исправлено; – Dariusz

+0

Я сделал несколько тестов и логический массив, кажется, примерно на 30% быстрее, чем если бы тест, что опять-таки в 10 раз быстрее регулярного выражения – krosenvold

0

Я полагаю, вы могли бы перебирать строки, получить код символа, сравнить с ASCII таблицы кодами. Таким образом, у каждого персонажа есть 3 between сравнения (для a-z, A-Z, 0-9) и 6 обычных целых сравнений для других символов. Я думаю, что это будет быстрее всего. Вы также можете попробовать многопоточный подход, в котором вы делаете в основном то же самое, но делите проблему на несколько частей перед запуском и выполните проверки одновременно.
Редактировать (после комментария @krosenvold): многопоточный подход подходит только для очень больших строк, потому что создание потоков имеет свою цену.

+4

Я думаю, вам понадобятся некоторые довольно огромные строки для многопоточного подхода, чтобы добраться куда угодно, я никогда не мог получить параллелизацию операций с этой детализацией, он редко работает хорошо для таких небольших операций, большая часть вычислений будет в кэше L1 процессора для такого алгоритма, где 1-ядерный сияет – krosenvold

Смежные вопросы