O compile()método é sempre chamado em algum ponto; é a única maneira de criar um objeto Padrão. Portanto, a questão é: por que você deveria chamá-lo explicitamente ? Um motivo é que você precisa de uma referência ao objeto Matcher para poder usar seus métodos, como group(int)recuperar o conteúdo de grupos de captura. A única maneira de obter o objeto Matcher é por meio do matcher()método do objeto Pattern , e a única maneira de obter o objeto Pattern é por meio do compile()método. Depois, há o find()método que, ao contrário matches(), não é duplicado nas classes String ou Pattern.
A outra razão é evitar criar o mesmo objeto Padrão repetidamente. Cada vez que você usa um dos métodos baseados em regex em String (ou o matches()método estático em Pattern), ele cria um novo Pattern e um novo Matcher. Portanto, este snippet de código:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... é exatamente equivalente a isto:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Obviamente, isso está fazendo um trabalho desnecessário. Na verdade, pode facilmente levar mais tempo para compilar a regex e instanciar o objeto Pattern do que para realizar uma correspondência real. Portanto, geralmente faz sentido retirar essa etapa do loop. Você também pode criar o Matcher com antecedência, embora eles não sejam tão caros:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Se você está familiarizado com regexes do .NET, pode estar se perguntando se o compile()método do Java está relacionado ao RegexOptions.Compiledmodificador do .NET ; a resposta é não. O Pattern.compile()método Java é meramente equivalente ao construtor Regex do .NET. Quando você especifica a Compiledopção:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... ele compila o regex diretamente para o código de byte CIL, permitindo um desempenho muito mais rápido, mas a um custo significativo no processamento inicial e no uso de memória - pense nisso como esteróides para regexes. Java não tem equivalente; não há diferença entre um padrão criado nos bastidores String#matches(String)e outro com o qual você cria explicitamente Pattern#compile(String).
(EDITAR: Eu disse originalmente que todos os objetos .NET Regex são armazenados em cache, o que é incorreto. Desde .NET 2.0, o armazenamento em cache automático ocorre apenas com métodos estáticos como Regex.Matches(), não quando você chama um construtor Regex diretamente. Ref )