Высокопроизводительные простые регулярные выражения Java

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

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

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

Если вы хотите избежать создания нового 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

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

Ответ 4

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

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