El método compile()
siempre se llama en algún momento; es la única forma de crear un objeto Pattern. Entonces, la pregunta es, ¿por qué debería llamarlo explícitamente? Una razón es que necesita una referencia al objeto Matcher para que pueda usar sus métodos, como group(int)
para recuperar los contenidos de los grupos de captura. La única manera de obtener el objeto Matcher es a través del método matcher()
del objeto Pattern, y la única manera de obtener el objeto Pattern es a través del método compile()
. Luego está el método find()
que, a diferencia de matches()
, no está duplicado en las clases String o Pattern.
La otra razón es evitar crear el mismo objeto Pattern una y otra vez. Cada vez que utiliza uno de los métodos de expresión regex en String (o el método estático matches()
en Patrón), crea un nuevo Patrón y un nuevo Matcher. Así que 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, que está haciendo una gran cantidad de trabajo innecesario. De hecho, puede tardar más tiempo en compilar la expresión regular y crear una instancia del objeto Pattern, que en realizar una coincidencia real. Entonces, por lo general, tiene sentido sacar ese paso del ciclo. Puede crear el Matcher antes de tiempo, así, aunque no son casi tan caro:
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("");
for (String s : myStringList) {
if (m.reset(s).matches()) {
doSomething();
}
}
Si está familiarizado con expresiones regulares de .NET, puede que se pregunte si el método de Java compile()
está relacionado con .NET de RegexOptions.Compiled
modificador; la respuesta es no. El método Pattern.compile()
de Java es simplemente equivalente al constructor Regex de .NET. Cuando especifica la opción Compiled
:
Regex r = new Regex(@"\d+", RegexOptions.Compiled);
...compila la expresión regular directamente al código de byte CIL, lo que le permite realizar un trabajo mucho más rápido, pero a un costo significativo en el procesamiento inicial y en el uso de la memoria. Piénselo como esteroides para las expresiones regulares. Java no tiene equivalente; no hay diferencia entre un Patrón creado detrás de escena por String#matches(String)
y uno que usted crea explícitamente con Pattern#compile(String)
.
(EDIT:.. Me dijo originalmente que todos los objetos .NET expresiones regulares se almacenan en caché, lo cual es incorrecto Desde .NET 2.0, el almacenamiento en caché automático se produce sólo con métodos estáticos como Regex.Matches()
, no cuando se llama a un constructor Regex directamente ref)
Bueno, la importancia es casi ninguno si la implementación (como en el JDK 1.7) es sólo una mera ATAJO al nuevo patrón (expresiones regulares, 0); Dicho esto, la REAL importancia no es el método estático en sí, sino la creación y el retorno de un nuevo patrón que se puede guardar para su uso posterior. Tal vez haya otras implementaciones en las que el método estático tome una nueva ruta y guarde en caché los objetos del Patrón, ¡y ese sería un caso real de la importancia de Pattern.compile()! – marcolopes
Las respuestas ponen de relieve la importancia de separar el patrón y combinar las clases (que es probablemente lo que hace la pregunta), pero nadie responde por qué no podemos simplemente utilizar un constructor 'nuevo patrón (regex)' en lugar de una función de compilación estática. marcolopes comment está en el lugar. –