2011-03-23 14 views
10

Conozco dos formas de reemplazar todas las apariciones de subcadenas en una cadena.Reemplazar todas las apariciones de subcadena en una cadena, ¿qué es más eficiente en Java?

La forma de expresiones regulares (asumiendo "-subcadena-a-ser reemplazado" no incluye caracteres especiales de expresiones regulares):

String regex = "substring-to-be-replaced" + "+"; 
Pattern scriptPattern = Pattern.compile(regex); 
Matcher matcher = scriptPattern.matcher(originalstring); 
newstring = matcher.replaceAll("replacement-substring"); 

El String.replace() así:

newstring = originalstring.replace("substring-to-be-replaced", "replacement-substring"); 

Qué de los dos es más eficiente (y por qué)?

¿Existen formas más eficaces que las dos anteriores?

+2

¿Qué quiere decir por eficiente? Menos drenaje de memoria? Menos tiempo de procesador? –

+0

Teniendo en cuenta que 'regex' funcionaría en' substring-to-be-replace + ', que solo permite múltiples' d's al final, ni siquiera se acercan a la misma cosa. –

+0

@Vladimir Ivanov Más rápido. –

Respuesta

12

String.replace() usa regex debajo.

public String replace(CharSequence target, CharSequence replacement) { 
     return Pattern.compile(target.toString(), Pattern.LITERAL) 
      .matcher(this).replaceAll(
       Matcher.quoteReplacement(replacement.toString())); 
    } 

¿Hay maneras más eficientes que los anteriores descritos dos?

No se dan que opere en una aplicación respaldada por ejemplo, mediante una matriz, en lugar de la clase String inmutable (ya string.replace crea una nueva cadena deen cada invocación). Ver por ejemplo StringBuilder.replace().

Compilar un regex implica bastante mucho de gastos generales que es claro al observar el Pattern source code. Afortunadamente, Apache ofrece un enfoque alternativo en StringUtils.replace() que según el source code (línea # 3732) es bastante eficiente.

+0

La implementación de String a la que apunta usa un 'Patrón' para el método de reemplazo en cuestión. – Jeremy

+0

@Johan Sjöberg StringBuilder.replace() no es lo mismo que String.replace() porque acepta índices de inicio y final en lugar de la "cadena por ser sustituida". –

+0

@Regex Novato, precisamente, eso es parte de lo que lo hace más eficiente –

1

En lugar de utilizar string s, que son inmutables, utilizar char matrices o algún otro tipo mutable (como StringBuffer o StringBuilder).

+0

Gracias por este consejo. ¿Puedes elaborar más sobre esto? Sé que la cadena original no se modifica cuando se usa replace(). ¿Puede dar un ejemplo? –

+0

intente utilizar un [StringBuffer] (http://download.oracle.com/javase/1.4.2/docs/api/java/lang/StringBuffer.html). – Davidann

+1

Un 'StringBuilder' sería más apropiado en situaciones no concurrentes. – Jeremy

0

¿No debería comparar replaceAll 2 veces? Sin embargo, para una invocación única difícilmente será medible. ¿Y harás millones de comparaciones?

Entonces esperaría que 'compilar' sea más rápido, pero solo, si no usa una cadena constante sin reglas de patrones.

¿Dónde está el problema al escribir un micro benchmark? O busca la fuente.

1

Sin haber hecho ningún perfil o evaluación comparativa, diría que es una apuesta bastante segura que si no necesitas magia regex, entonces la sobrecarga del analizador de expresiones regulares (que obtendrás no importa qué, en términos de memoria, así como el uso de la CPU) le cuesta mucho más de lo que posiblemente puede ganar en el otro extremo.

2

Aquí está la source code de OpenJDK:

public String replace(CharSequence target, CharSequence replacement) { 
    return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
     this).replaceAll(Matcher.quoteReplacement(replacement.toString())); 
} 
+1

Por lo tanto, resulta que, si uno tiene que reemplazar la misma cadena a menudo, uno estará mejor con replaceAll usando un Regex precompilado. – Ingo

Cuestiones relacionadas