Какая разница между String.matches и Matcher.matches? Есть ли разница в производительности или других вещах?
Какая разница между String.matches и Matcher.matches?
Ответ 1
Совершенно верно. A Matcher
создается в предварительно скомпилированном регулярном выражении, а String.matches
должен перекомпилировать регулярное выражение каждый раз, когда он выполняется, поэтому он становится более расточительным, чем чаще вы запускаете эту строку кода.
Ответ 2
String.matches внутренне делегирует Matcher.matches.
public boolean matches(String regex) {
return Pattern.matches(regex, this);
}
public static boolean matches(String regex, CharSequence input) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(input);
return m.matches();
}
Если вы повторно используете объект Pattern, тогда будет некоторое преимущество в производительности. Также при использовании Pattern/Matcher вы можете group ваши регулярные выражения и получить соответствующие части.
Если вы используете регулярное выражение, которое вы будете использовать только один раз, и вам не нужно анализировать вашу строку, чтобы получить соответствующие части, то используйте их. Но если вы собираетесь использовать одно и то же регулярное выражение для нескольких строк или вам нужны части строки на основе регулярного выражения, создайте шаблон и получите его, используя его.
Ответ 3
Из любопытства я сделал этот небольшой тест по разнице во времени. Оказывается, что с использованием предварительно скомпилированного шаблона более чем в 5 раз быстрее, чем с использованием метода String.matches.
import java.util.regex.Pattern;
/**
* @author Rajind Ruparathna
*/
public class MatchesTest {
public static void main(String Args[]) {
String first = "@\\{message.headers\\.?([^\\}]*)\\}";
String second = "@\\{message.headers.wolla\\}";
long start, end, total;
float avg;
int NUM_OF_ITERATIONS = 100;
Pattern pattern = Pattern.compile(first);
total = 0;
start = 0;
end = 0;
avg = 0;
for (int i=0; i< NUM_OF_ITERATIONS; i++) {
start = System.nanoTime();
pattern.matcher(second).matches();
end = System.nanoTime();
total = total + (end - start);
}
avg = total/NUM_OF_ITERATIONS;
System.out.println("Duration pre compiled: " + avg);
total = 0;
start = 0;
end = 0;
avg = 0;
for (int i=0; i< NUM_OF_ITERATIONS; i++) {
start = System.nanoTime();
first.matches(second);
end = System.nanoTime();
total = total + (end - start);
}
avg = total/NUM_OF_ITERATIONS;
System.out.println("In place compiled: " + avg);
}
}
Выход (наносекунды):
Продолжительность предварительной компиляции: 4505.0
Скомпилировано: 44960.0
Ответ 4
String.matches
внутренне вызывает Pattern.matches(regex, str)
.
Проблема заключается в том, что каждый раз, когда вы его называете, вы перекомпилируете шаблон, который стоит несколько ресурсов.
Лучше скомпилировать свой шаблон один раз, а затем попытаться сопоставить его со всеми необходимыми строками. Я лично использую класс Patterns, содержащий все мои шаблоны в моем приложении, объявленные как final и static
Ответ 5
Смотрите сами: http://www.docjar.com/html/api/java/lang/String.java.html строка 2101.
Ответ 6
Pattern.compile компилирует шаблон таким образом, что при выполнении metcher.matches шаблон снова не компилируется снова и снова. Pattern.compile pre компилирует его. Однако, если вы используете string.matches, он компилирует шаблон каждый раз, когда вы выполняете эту строку. Итак, лучше использовать Pattern.compile.