compile()
Метод всегда вызывается в какой - то момент; это единственный способ создать объект Pattern. Итак, вопрос в том, почему вы должны называть это явно ? Одна из причин заключается в том, что вам нужна ссылка на объект Matcher, чтобы вы могли использовать его методы, например, group(int)
для получения содержимого групп захвата. Единственный способ получить объект Matcher - использовать метод объекта Pattern matcher()
, а единственный способ получить объект 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, вам может быть интересно, compile()
связан ли метод Java с RegexOptions.Compiled
модификатором .NET ; ответ - нет. Pattern.compile()
Метод Java просто эквивалентен конструктору Regex в .NET. Когда вы указываете Compiled
опцию:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... он компилирует регулярное выражение непосредственно в байтовый код CIL, что позволяет ему работать намного быстрее, но со значительными затратами на предварительную обработку и использование памяти - думайте об этом как о стероидах для регулярных выражений. Java не имеет эквивалента; нет никакой разницы между шаблоном, который создается за кулисами, String#matches(String)
и шаблоном, который вы создаете явно Pattern#compile(String)
.
(РЕДАКТИРОВАТЬ: я изначально сказал, что все объекты .NET Regex кэшируются, что неверно. Начиная с .NET 2.0, автоматическое кеширование происходит только со статическими методами, например Regex.Matches()
, а не при прямом вызове конструктора Regex. Ref )