Высокопроизводительные простые регулярные выражения Java - PullRequest
10 голосов
/ 21 сентября 2011

Часть кода, над которым я работаю, использует несколько регулярных выражений для поиска простых строковых шаблонов (например, таких шаблонов, как "foo [0-9] {3,4} bar"). В настоящее время мы используем статически скомпилированные шаблоны Java и затем вызываем Pattern#matcher, чтобы проверить, содержит ли строка совпадение с шаблоном (мне не нужно совпадение, просто логическое значение, указывающее, есть ли совпадение). Это приводит к заметному выделению памяти, что влияет на производительность.

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

Ответы [ 4 ]

13 голосов
/ 21 сентября 2011

Попробуйте matcher.reset("newinputtext") метод, чтобы избежать создания новых совпадений при каждом вызове Pattern.matcher.

4 голосов
/ 22 сентября 2011

Если вы ожидаете, что менее 50% строк соответствуют вашему регулярному выражению, вы можете сначала попытаться проверить некоторую подпоследовательность с помощью String.indexOf(), что примерно в 3-20 раз быстрее для простой последовательности по сравнению с регулярным выражением:

if (line.indexOf("foo")>-1) && pattern.matcher(line).matches()) {
    ...

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

2 голосов
/ 22 сентября 2011

Если вы хотите избежать создания нового Matcher для каждого паттерна, используйте метод usePattern(), например:

Pattern[] pats = {
  Pattern.compile("123"),
  Pattern.compile("abc"),
  Pattern.compile("foo")
};
String s = "123 abc";
Matcher m = Pattern.compile("dummy").matcher(s);
for (Pattern p : pats)
{
  System.out.printf("%s : %b%n", p.pattern(), m.reset().usePattern(p).find());
}

см. Демонстрацию на Ideone

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

0 голосов
/ 21 сентября 2011

Вы можете попробовать использовать статический метод Pattern.matches(), который просто возвращает логическое значение. Это не вернуло бы объект Matcher, так что это могло бы помочь с проблемами выделения памяти.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...