El compile()
método siempre se llama en algún momento; es la única forma de crear un objeto Patrón. Entonces la pregunta es realmente, ¿por qué debería llamarlo explícitamente ? Una razón es que necesita una referencia al objeto Matcher para poder usar sus métodos, como group(int)
recuperar el contenido de los grupos de captura. La única forma de obtener el objeto Matcher es a través del matcher()
método del objeto Pattern , y la única forma de obtener el objeto Pattern es a través del compile()
método. Luego está el find()
método que, a diferencia matches()
, no está duplicado en las clases String o Pattern.
La otra razón es evitar crear el mismo objeto Patrón una y otra vez. Cada vez que utiliza uno de los métodos basados en expresiones regulares en String (o el matches()
método estático en Pattern), crea un nuevo Pattern y un nuevo Matcher. Entonces este fragmento de código:
for (String s : myStringList) {
if ( s.matches("\\d+") ) {
doSomething();
}
}
... es exactamente equivalente a esto:
for (String s : myStringList) {
if ( Pattern.compile("\\d+").matcher(s).matches() ) {
doSomething();
}
}
Obviamente, eso está haciendo mucho trabajo innecesario. De hecho, puede llevar más tiempo compilar la expresión regular y crear una instancia del objeto Pattern que realizar una coincidencia real. Entonces, por lo general, tiene sentido sacar ese paso del círculo. También puede crear el Matcher con anticipación, aunque no son tan caros:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if ( m.reset(s).matches() ) {
doSomething();
}
}
Si está familiarizado con las expresiones regulares de .NET, puede que se pregunte si el compile()
método de Java está relacionado con el RegexOptions.Compiled
modificador de .NET ; la respuesta es no. El Pattern.compile()
método de Java es simplemente equivalente al constructor Regex de .NET. Cuando especifica la Compiled
opción:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
... compila la expresión regular directamente en el código de bytes CIL, lo que le permite funcionar mucho más rápido, pero a un costo significativo en el procesamiento inicial y el uso de memoria; considérelo como esteroides para expresiones regulares. Java no tiene equivalente; no hay diferencia entre un patrón creado detrás de escena String#matches(String)
y uno con el que crea explícitamente Pattern#compile(String)
.
(EDITAR: originalmente dije que todos los objetos .NET Regex se almacenan en caché, lo cual es incorrecto. Desde .NET 2.0, el almacenamiento en caché automático ocurre solo con métodos estáticos como Regex.Matches()
, no cuando se llama a un constructor Regex directamente. Ref )