2010-03-18 9 views

Respuesta

38

Absolutamente. Se crea un Matcher en una expresión regular precompilada, mientras que String.matches debe recompilar la expresión regular cada vez que se ejecuta, por lo que se vuelve un desperdicio más a menudo se ejecuta esa línea de código.

5

String.matches llamadas internas Pattern.matches(regex, str). El problema es que cada vez que lo llamas, recompilas el patrón, lo que cuesta algunos recursos.

Es mejor compilar su patrón una vez, luego intente hacer coincidirlo con todas las cadenas que desee. Yo personalmente uso una clase de Patrones que contiene todo mi patrón en mi aplicación declarada como definitiva y estática

+2

"Yo personalmente uso una clase de Patrones que contiene todo mi patrón en mi aplicación declarada como definitiva y estática." Es mejor poner los patrones en las clases o métodos donde se usan realmente. De esta forma, el código que cambia conjuntamente se empaqueta. Consulte el [Principio de cierre común] (http://c2.com/cgi/wiki?CommonClosurePrinciple). –

+1

de hecho, estoy de acuerdo contigo. Mis opiniones han cambiado en 4 años :-) – chburd

23

String.matches delega internamente en Matcher.matches.

public boolean matches(String regex) { 
    return Pattern.matches(regex, this); 
} 

public static boolean matches(String regex, CharSequence input) { 
    Pattern p = Pattern.compile(regex); 
    Matcher m = p.matcher(input); 
    return m.matches(); 
} 

Si está reutilizando el objeto Pattern, habrá algunos beneficios de rendimiento. Además, cuando utiliza Pattern/Matcher puede group sus expresiones regulares y obtener las partes correspondientes.

La línea de fondo es si tiene una expresión regular que usará solo una vez y no necesita analizar su cadena para obtener partes coincidentes y luego usar cualquiera. Pero si vas a usar la misma expresión regular contra varias cadenas o si necesitas partes de la cadena basadas en expresiones regulares, crea un patrón y obtén Matcher usándolo.

8

Por curiosidad he hecho este pequeño ensayo sobre las diferencias de tiempo. Resulta que usando un patrón precompilado es más de 5 veces más rápido que usando el método String.matches.

import java.util.regex.Pattern; 

/** 
* @author Rajind Ruparathna 
*/ 
public class MatchesTest { 
    public static void main(String Args[]) { 
     String first = "@\\{message.headers\\.?([^\\}]*)\\}"; 
     String second = "@\\{message.headers.wolla\\}"; 
     long start, end, total; 
     float avg; 
     int NUM_OF_ITERATIONS = 100; 

     Pattern pattern = Pattern.compile(first); 

     total = 0; 
     start = 0; 
     end = 0; 
     avg = 0; 

     for (int i=0; i< NUM_OF_ITERATIONS; i++) { 
      start = System.nanoTime(); 
      pattern.matcher(second).matches(); 
      end = System.nanoTime(); 
      total = total + (end - start); 
     } 
     avg = total/NUM_OF_ITERATIONS; 
     System.out.println("Duration pre compiled: " + avg); 

     total = 0; 
     start = 0; 
     end = 0; 
     avg = 0; 

     for (int i=0; i< NUM_OF_ITERATIONS; i++) { 
      start = System.nanoTime(); 
      first.matches(second); 
      end = System.nanoTime(); 
      total = total + (end - start); 
     } 
     avg = total/NUM_OF_ITERATIONS; 
     System.out.println("In place compiled: " + avg); 
    } 
} 

de salida (nanosegundos):

duración predeterminada de compilar: 4505,0

En lugar de compilar: 44960.0

P.S. Esta prueba es una prueba rápida y sucia, y puede no estar de acuerdo con las prácticas de evaluación comparativa del rendimiento. Si desea obtener resultados altamente precisos, utilice una herramienta de micro benchmarking.

+1

Este es el punto de referencia que estaba buscando, ¡gracias! – Tadhg

0

Pattern.compile compila el patrón para que cuando ejecute metcher.matches, el patrón no se vuelva a compilar una y otra vez. Pattern.compile lo compila previamente. Sin embargo, si usa string.matches, compila el patrón cada vez que ejecuta esta línea. Entonces, es mejor usar Pattern.compile.

Cuestiones relacionadas