Метод compile()
всегда вызывается в какой-то момент; это единственный способ создать объект Pattern. Таким образом, вопрос в том, почему вы должны называть это явно ? Одна из причин заключается в том, что вам нужна ссылка на объект Matcher, чтобы вы могли использовать его методы, например group(int)
, для извлечения содержимого групп захвата. Единственный способ получить объект Matcher - метод matcher()
объекта Pattern, а единственный способ получить объект Pattern - метод compile()
. Тогда есть метод find()
, который, в отличие от matches()
, не дублируется в классах String или Pattern.
Другая причина - избегать создания одного и того же объекта Pattern снова и снова. Каждый раз, когда вы используете один из методов на основе регулярных выражений в String (или статический метод matches()
в Pattern), он создает новый Pattern и новый Matcher. Итак, этот фрагмент кода:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... в точности соответствует этому:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Очевидно, это делает много ненужной работы. Фактически, для компиляции регулярного выражения и создания экземпляра объекта Pattern может потребоваться больше времени, чем для фактического сопоставления. Поэтому обычно имеет смысл вытащить этот шаг из цикла. Вы также можете создать Matcher заранее, хотя они и не такие дорогие:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Если вы знакомы с регулярными выражениями .NET, вам может быть интересно, связан ли метод Java compile()
с модификатором .NET RegexOptions.Compiled
; ответ - нет. Java Pattern.compile()
метод просто эквивалентен конструктору Regex .NET. При указании опции Compiled
:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... он компилирует регулярное выражение непосредственно в байт-код CIL, что позволяет ему работать намного быстрее, но при значительных затратах на предварительную обработку и использование памяти - считайте его стероидами для регулярных выражений. Java не имеет аналогов; нет никакой разницы между шаблоном, который создается за сценой с помощью String#matches(String)
, и шаблоном, который вы создаете явно с помощью Pattern#compile(String)
.
(EDIT: я изначально говорил, что все объекты .NET Regex кэшируются, что неверно. Начиная с .NET 2.0 автоматическое кэширование происходит только со статическими методами, такими как Regex.Matches()
, а не при непосредственном вызове конструктора Regex. ссылка )