2013-03-05 2 views
5

Я пытаюсь улучшить производительность некоторого кода. Это выглядит примерно так:Как определить, является ли строка не регулярным выражением?

public boolean isImportant(String token) { 
    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    } 
} 

То, что я заметил, что многие из шаблонов кажутся простыми строковые литералы, не имеющие регулярных выражений конструкций. Поэтому я хочу, чтобы просто хранить их в отдельном списке (importantList) и сделать проверку равенства вместо выполнения более дорогой матч шаблон, например, следующим образом:

public boolean isImportant(String token) { 
    if (importantList.contains(token)) return true; 

    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    }   
} 

Как программно определить, является ли конкретная строка не содержит конструкции регулярных выражений?

Редактировать: Я должен добавить, что ответ не обязательно должен быть чувствительным к характеристикам. (т. е. можно использовать регулярные выражения). В основном я занимаюсь производительностью isImportant(), потому что он называется миллионы раз, а инициализация шаблонов выполняется только один раз.

+1

Не выполнял бы регулярное выражение в строке, чтобы определить, является ли это регулярным выражением каждый раз намного хуже, чем просто использовать каждую строку в качестве регулярного выражения? –

+3

@MikeM: Это не то, что он спрашивает. 'hello' - отлично действующее регулярное выражение. –

+0

Невозможно (по крайней мере, не легко или стоит, если вы не найдете какой-либо шаблон в простых строковых литералах). Простой строковый литерал является допустимым шаблоном регулярного выражения. – AC1

ответ

3

Это будет сложно. Вы можете проверить отсутствие каких-либо метасимволов регулярных выражений; что должно быть хорошим приближением:

Pattern regex = Pattern.compile("[$^()\\[\\]{}.*+?\\\\]"); 
Matcher regexMatcher = regex.matcher(subjectString); 
regexIsLikely = regexMatcher.find(); 

Стоит ли это другого вопроса. Вы уверены, что регулярное совпадение медленнее, чем просмотр списка (тем более, что после этого во многих случаях вы будете выполнять регулярное выражение)? Я бы поспорил, что гораздо быстрее сохранить соответствие регулярному выражению.

+0

Это решение, с которым я пошел. Интересно, что я сократил время обработки примерно на 50%. –

4

Я обычно ненавижу ответы, которые говорят это, но ...

Не делай этого.

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

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

+0

Я намереваюсь, чтобы профилировщик ответил на вопрос, важны ли оптимизации. –

2

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

+1

Это зависит, но я бы оценил, что Java пытается сделать гораздо более эффективное регулярное выражение DFA и только свопы к NFA, если это требует выражение (например, если оно включает в себя поиск) –

1

Это неправильно

for (Pattern pattern : patterns) 

вы должны создать одно большое регулярное выражение, которое OR всех моделей; то для каждого входа один раз один раз.

+0

Спасибо. Я на самом деле это сделал, и оказалось, что использование одного гигантского шаблона было на 1/3 быстрее, чем сопоставление с несколькими маленькими узорами. –

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