Diferencia entre String replace () y replaceAll ()

221

¿Cuál es la diferencia entre java.lang.String replace()y los replaceAll()métodos, aparte de los usos posteriores de regex? Para sustituciones simples como, reemplazar .con / , ¿hay alguna diferencia?

Jijoy
fuente

Respuestas:

174

En java.lang.String, el replacemétodo toma un par de char o un par de CharSequence(de los cuales String es una subclase, por lo que felizmente tomará un par de String). El replacemétodo reemplazará todas las apariciones de un char o CharSequence. Por otro lado, ambos Stringargumentos replaceFirsty replaceAllson expresiones regulares (regex). Usar la función incorrecta puede provocar errores sutiles.

emilan
fuente
30
Además, según los documentos de Java, cada llamada a str.replaceAll(regex, repl)es igual a Pattern.compile(regex).matcher(str).replaceAll(repl). Entonces, hay una gran sobrecarga dependiendo de cuánto se use.
user845279
44
@ user845279 Es interesante que diría que ya que String#replace(target, replacement)hace lo mismo, excepto que cita las cadenas: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));¿Hay alguna razón por la String#replaceque sería más rápido que String#replaceAll? No lo parecería, ya que String#replacesolo realiza operaciones adicionales.
Horsey
1
Simplemente curioso, en esta respuesta, ¿dónde está la comparación explícita en contra replaceAll? La respuesta es más sobrereplace
Manuel Jordan
Esto significa que replaceAll () sería más costoso debido a la coincidencia de expresiones regulares? ¿No es así?
pregunto el
98

P: ¿Cuál es la diferencia entre los java.lang.Stringmétodos replace()y replaceAll(), aparte de eso, el último usa regex?

A: Solo la expresión regular. Ambos reemplazan a todos :)

http://docs.oracle.com/javase/6/docs/api/java/lang/String.html

PD:

También hay un replaceFirst()(que toma una expresión regular)

paulsm4
fuente
1
Gracias por la aclaración de que es solo la expresión regular. Cómo desearía que lo hubieran nombrado replaceWithRegex () en lugar de replaceAll ()
HopeKing
Aclaración: replaceAll () funciona con expresiones regulares, replace () funciona con CharSequence
Johnny Five
2
@JohnnyFive Eso lo hace más confuso. La expresión regular no es un tipo, CharSequencees. Ambos replace()y replaceAll()"trabajar con CharSequence". Es que replaceAll()considera lo dado CharSequencecomo una expresión regular, por lo que busca coincidencias de expresiones regulares , mientras que replace()considera lo dado CharSequencecomo un texto de búsqueda simple, por lo que busca ocurrencias de él.
SantiBailors
43

Ambos replace()y replaceAll()reemplazar todas las ocurrencias en la cadena.

Ejemplos

Siempre encuentro ejemplos útiles para entender las diferencias.

replace()

Úselo replace()si solo desea reemplazar algunos charcon otros charo algunos Stringcon otros String(en realidad CharSequence).

Ejemplo 1

Reemplace todas las ocurrencias del personaje xcon o.

String myString = "__x___x___x_x____xx_";

char oldChar = 'x';
char newChar = 'o';

String newString = myString.replace(oldChar, newChar);
// __o___o___o_o____oo_

Ejemplo 2

Reemplace todas las ocurrencias de la cadena fishcon sheep.

String myString = "one fish, two fish, three fish";

String target = "fish";
String replacement = "sheep";

String newString = myString.replace(target, replacement);
// one sheep, two sheep, three sheep

replaceAll()

Úselo replaceAll()si desea utilizar un patrón de expresión regular .

Ejemplo 3

Reemplace cualquier número con un x.

String myString = "__1_6____3__6_345____0";

String regex = "\\d";
String replacement = "x";

String newString = myString.replaceAll(regex, replacement); 
// __x_x____x__x_xxx____x

Ejemplo 4

Eliminar todos los espacios en blanco.

String myString = "   Horse         Cow\n\n   \r Camel \t\t Sheep \n Goat        ";

String regex = "\\s";
String replacement = "";

String newString = myString.replaceAll(regex, replacement); 
// HorseCowCamelSheepGoat

Ver también

Documentación

Expresiones regulares

Suragch
fuente
34

El replace()método se sobrecarga para aceptar tanto un primitivo charcomo un CharSequenceargumento.

Ahora, en lo que respecta al rendimiento, el replace()método es un poco más rápido que replaceAll()porque este último compila primero el patrón regex y luego coincide antes de finalmente reemplazarlo, mientras que el primero simplemente coincide con el argumento proporcionado y reemplaza.

Ya que sabemos que la coincidencia de patrones de expresiones regulares es un poco más complejo y por lo tanto más lento, a continuación, prefiriendo replace()más replaceAll()se sugiere siempre que sea posible.

Por ejemplo, para sustituciones simples como usted mencionó, es mejor usar:

replace('.', '\\');

en vez de:

replaceAll("\\.", "\\\\");

Nota: los argumentos del método de conversión anteriores dependen del sistema.

Surender Thakran
fuente
66
Incluso reemplazar también hace lo mismo, From java String docs :: public String replace (destino CharSequence, reemplazo CharSequence) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (replace.toString ())); }
Prateek
@Prateek: después de jdk8, String :: replace ya no usa Pattern: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , lo mismo en jdk11.
Franck
De acuerdo, en Java 8 prácticamente ambos métodos son casi iguales, ya que ambos aparecen el Pattern.compile(...)contenido / parte en sus implementaciones, parece que replacees menos complejo sobre cómo definir / enviar el primer argumento. No requiere "\". Además replaceestá disponible desde Java 1.5y replaceAlldesde1.4
Manuel Jordan
3
String replace(char oldChar, char newChar)

Devuelve una nueva cadena resultante de reemplazar todas las apariciones de oldChar en esta cadena con newChar.

String replaceAll(String regex, String replacement

Reemplaza cada subcadena de esta cadena que coincide con la expresión regular dada con el reemplazo dado.

S. Rahul
fuente
3
  1. Ambos replace () y replaceAll () aceptan dos argumentos y reemplazan todas las apariciones de la primera subcadena (primer argumento) en una cadena con la segunda subcadena (segundo argumento).
  2. replace () acepta un par de char o charsequence y replaceAll () acepta un par de expresiones regulares.
  3. No es cierto que replace () funcione más rápido que replaceAll () ya que ambos usan el mismo código en su implementación

    Pattern.compile (regex) .matcher (this) .replaceAll (reemplazo);

Ahora la pregunta es cuándo usar replace y cuándo usar replaceAll (). Cuando desee reemplazar una subcadena con otra subcadena independientemente de su lugar de aparición en la cadena, use replace (). Pero si tiene alguna preferencia o condición particular, como reemplazar solo esas subcadenas al principio o al final de una cadena, use replaceAll (). Aquí hay algunos ejemplos para probar mi punto:

String str = new String("==qwerty==").replaceAll("^==", "?"); \\str: "?qwerty=="
String str = new String("==qwerty==").replaceAll("==$", "?"); \\str: "==qwerty?"
String str = new String("===qwerty==").replaceAll("(=)+", "?"); \\str: "?qwerty?"
Aarya
fuente
44
No son exactamente la misma implementación. replaceno llama Pattern.compile(regex).matcher(this).replaceAll(replacement);. LlamaPattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils
replaceAll () acepta un par de expresiones regulares ¿Por qué tanto la cadena de búsqueda como la cadena de reemplazo serían una expresión regular? ¿Con qué se reemplazarían las ocurrencias? Con una expresión regular? Por supuesto, solo el primer argumento es una expresión regular (la cadena de búsqueda). El segundo no es una expresión regular (la cadena de reemplazo).
SantiBailors
1

Como se aludió en la respuesta de wickeD, con replaceAll la cadena de reemplazo se maneja de manera diferente entre replace y replaceAll. Esperaba que un [3] y un [4] tuvieran el mismo valor, pero son diferentes.

public static void main(String[] args) {
    String[] a = new String[5];
    a[0] = "\\";
    a[1] = "X";
    a[2] = a[0] + a[1];
    a[3] = a[1].replaceAll("X", a[0] + "X");
    a[4] = a[1].replace("X", a[0] + "X");

    for (String s : a) {
        System.out.println(s + "\t" + s.length());
    }
}

El resultado de esto es:

\   1
X   1
\X  2
X   1
\X  2

Esto es diferente de perl donde el reemplazo no requiere el nivel adicional de escape:

#!/bin/perl
$esc = "\\";
$s = "X";

$s =~ s/X/${esc}X/;
print "$s " . length($s) . "\n";

que imprime \ X 2

Esto puede ser bastante molesto, como cuando se trata de usar el valor devuelto por java.sql.DatabaseMetaData.getSearchStringEscape () con replaceAll ().

Keith Crews
fuente
0

Hilo antiguo que conozco, pero soy algo nuevo en Java y descubro una de sus cosas extrañas. Lo he usado String.replaceAll()pero obtengo resultados impredecibles.

Algo así desordena la cadena:

sUrl = sUrl.replaceAll( "./", "//").replaceAll( "//", "/");

Así que diseñé esta función para solucionar el extraño problema:

//String.replaceAll does not work OK, that's why this function is here
public String strReplace( String s1, String s2, String s ) 
{
    if((( s == null ) || (s.length() == 0 )) || (( s1 == null ) || (s1.length() == 0 )))
     { return s; }

   while( (s != null) && (s.indexOf( s1 ) >= 0) )
    { s = s.replace( s1, s2 ); }
  return s;
}

Lo que te permite hacer:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );
Codebeat
fuente
1
String.replaceAll()espera expresiones regulares, no argumentos literales, por lo que obtienes resultados "impredecibles" (que en realidad son muy predecibles). String.replace()funciona de la manera que quieras.
Nadar
Como regla general para cuando obtenemos resultados inesperados de Java, en lugar de diseñar una nueva función para evitar eso, es mejor suponer que esos resultados son correctos y que estamos malentendiendo la funcionalidad de Java que estamos utilizando.
SantiBailors
0

Para agregar a la "Mejor respuesta" ya seleccionada (y otras que son tan buenas como la de Suragch), String.replace()se limita al reemplazar los caracteres que son secuenciales (tomando así CharSequence). Sin embargo, String.replaceAll()no está limitado al reemplazar solo caracteres secuenciales. Puede reemplazar los caracteres no secuenciales, siempre y cuando su expresión regular se construya de esa manera.

Además (lo más importante y dolorosamente obvio), replace()solo puede reemplazar los valores literales; mientras que replaceAllpuede reemplazar secuencias 'similares' (no necesariamente idénticas).

hfontanez
fuente
-1

replace()el método no usa el patrón regex, mientras que el replaceAll()método usa el patrón regex. Por lo tanto, replace()realiza más rápido que replaceAll().

un hombre
fuente
3
eso no es cierto. Si observa la fuente de reemplazo, verá que también utilizó el Patrón y el Matcher (es decir, la expresión regular)
xtrakBandit
-5

replace funciona en el tipo de datos char pero replaceAll funciona en el tipo de datos String y ambos reemplazan todas las apariciones del primer argumento con el segundo argumento.

Pramod Kumar
fuente