Diferença entre String replace () e replaceAll ()

221

Qual é a diferença entre java.lang.String replace()e replaceAll()métodos, além de usar regex? Para substituições simples como, substitua .por / , há alguma diferença?

Jijoy
fonte

Respostas:

174

Em java.lang.String, o replacemétodo pega um par de caracteres ou um par de CharSequence's (dos quais String é uma subclasse, portanto, é necessário um par de String). O replacemétodo substituirá todas as ocorrências de um caractere ou CharSequence. Por outro lado, ambos os Stringargumentos replaceFirste replaceAllsão expressões regulares (regex). Usar a função errada pode levar a erros sutis.

emilan
fonte
30
Além disso, de acordo com os documentos java, cada chamada para str.replaceAll(regex, repl)é igual a Pattern.compile(regex).matcher(str).replaceAll(repl). Portanto, existe uma grande sobrecarga, dependendo de quanto é usado.
User845279
4
@ user845279 É interessante que você diria que, já que String#replace(target, replacement)faz a mesma coisa, exceto que cita as strings: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));existe alguma razão pela qual String#replaceseria mais rápido do que String#replaceAll? Parece que não, pois String#replaceapenas realiza operações adicionais.
Horsey
1
Apenas curioso, nesta resposta, onde está a comparação explícita contra replaceAll. A resposta é mais sobrereplace
Manuel Jordan
isso significa que substituirAll () seria mais caro devido à correspondência de regex? não é?
perguntei
97

P: Qual a diferença entre os java.lang.Stringmétodos replace()e replaceAll(), além disso, o último usa regex.

A: Apenas o regex. Ambos substituem todos :)

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

PS:

Há também um replaceFirst()(que usa uma regex)

paulsm4
fonte
1
Agradecemos o esclarecimento de que é apenas o regex. Como eu gostaria que eles tivessem nomeou-replaceWithRegex () em vez de replaceAll ()
HopeKing
Esclarecimento: replaceAll () trabalha com expressões regulares, replace () trabalha com CharSequence
Johnny Five
2
@JohnnyFive Isso torna mais confuso. Expressão regular não é um tipo, CharSequenceé. Ambos replace()e replaceAll()"trabalham com CharSequence". É que replaceAll()considera o dado CharSequencecomo uma expressão regular para procurar correspondências de expressões regulares , enquanto replace()considera o dado CharSequencecomo um texto de pesquisa simples para procurar ocorrências dele.
SantiBailors
43

Ambos replace()e replaceAll()substituem todas as ocorrências na String.

Exemplos

Eu sempre acho exemplos úteis para entender as diferenças.

replace()

Use replace()se você quiser substituir alguns charpor outro charou outros Stringpor outro String(na verdade CharSequence).

Exemplo 1

Substitua todas as ocorrências do personagem xpor 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_

Exemplo 2

Substitua todas as ocorrências da sequência fishpor 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()

Use replaceAll()se você quiser usar um padrão de expressão regular .

Exemplo 3

Substitua qualquer número por um 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

Exemplo 4

Remova todo o espaço em branco.

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

Veja também

Documentação

Expressões regulares

Suragch
fonte
34

O replace()método está sobrecarregado para aceitar argumentos primitivo chare a CharSequenceas.

Agora, no que diz respeito ao desempenho, o replace()método é um pouco mais rápido do que replaceAll()porque o último primeiro compila o padrão regex e, em seguida, corresponde antes de finalmente substituir, enquanto o anterior simplesmente corresponde ao argumento fornecido e substitui.

Como sabemos que a correspondência do padrão regex é um pouco mais complexa e, consequentemente, mais lenta, a preferência pelo replace()excesso replaceAll()é sugerida sempre que possível.

Por exemplo, para substituições simples como você mencionou, é melhor usar:

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

ao invés de:

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

Nota: os argumentos do método de conversão acima dependem do sistema.

Surender Thakran
fonte
6
Mesmo substituir também faça o mesmo: De java String docs :: public String replace (destino CharSequence, substituição CharSequence) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (substituição.paraString ())); }
Prateek
@Prateek: depois do jdk8, String :: replace não está mais usando o Pattern: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , o mesmo no jdk11.
Franck
Concordo, no Java 8 praticamente os dois métodos são quase os mesmos, pois ambos aparecem o Pattern.compile(...)conteúdo / parte em suas implementações, parece replaceser menos complexo sobre como definir / enviar o primeiro argumento. Não requer "\". Além disso, replaceestá disponível desde Java 1.5e replaceAlldesde1.4
Manuel Jordan
3
String replace(char oldChar, char newChar)

Retorna uma nova string resultante da substituição de todas as ocorrências de oldChar nessa string por newChar.

String replaceAll(String regex, String replacement

Substitui cada substring dessa string que corresponde à expressão regular especificada pela substituição especificada.

S. Rahul
fonte
3
  1. Substituir () e replaceAll () aceita dois argumentos e substitui todas as ocorrências da primeira substring (primeiro argumento) em uma string pela segunda substring (segundo argumento).
  2. replace () aceita um par de char ou charsequence e replaceAll () aceita um par de regex.
  3. Não é verdade que replace () funciona mais rápido que replaceAll (), pois ambos usam o mesmo código em sua implementação

    Pattern.compile (regex) .matcher (this) .replaceAll (substituição);

Agora, a questão é quando usar replace e quando usar replaceAll (). Quando você deseja substituir uma subcadeia por outra subcadeia, independentemente de seu local de ocorrência na cadeia, use replace (). Mas se você tiver alguma preferência ou condição específica, como substituir apenas as substrings no início ou no final de uma string, use replaceAll (). Aqui estão alguns exemplos para provar meu argumento:

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
fonte
4
Eles não são exatamente a mesma implementação. replacenão liga Pattern.compile(regex).matcher(this).replaceAll(replacement);. Ele chama #Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils 5/16
replaceAll () aceita um par de regex Por que a cadeia de pesquisa e a cadeia de substituição seriam uma regex? Com o que as ocorrências seriam substituídas? Com uma regex? Obviamente, apenas o primeiro argumento é uma expressão regular (a sequência de pesquisa). O segundo não é um regex (a sequência de substituição).
SantiBailors
1

Conforme mencionado na resposta do wickeD, com replaceAll, a cadeia de substituição é tratada de maneira diferente entre replace e replaceAll. Eu esperava que um [3] e um [4] tivessem o mesmo valor, mas eles são 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());
    }
}

A saída disso é:

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

Isso é diferente do perl, onde a substituição não requer o nível extra de escape:

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

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

que imprime \ X 2

Isso pode ser um incômodo, como ao tentar usar o valor retornado por java.sql.DatabaseMetaData.getSearchStringEscape () com replaceAll ().

Keith Crews
fonte
0

Tópico antigo que conheço, mas sou um pouco novo em Java e descubro uma de suas coisas estranhas. Eu usei, String.replaceAll()mas obtive resultados imprevisíveis.

Algo assim bagunça a corda:

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

Então, eu projetei essa função para contornar o estranho 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;
}

O que o torna capaz de fazer:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );
Codebeat
fonte
1
String.replaceAll()espera expressões regulares, não argumentos literais, e é por isso que você obtém resultados "imprevisíveis" (que são realmente muito previsíveis). String.replace()funciona da maneira que você deseja.
Nadar
Como regra geral, quando obtemos resultados inesperados do Java, em vez de projetar uma nova função para contornar isso, é melhor supor que esses resultados estejam certos e que estamos entendendo mal a funcionalidade Java que estamos usando.
SantiBailors 12/04/19
0

Para adicionar à "Melhor resposta" já selecionada (e outras que são tão boas quanto as de Suragch), a String.replace()restrição é substituída pela substituição de caracteres que são seqüenciais (levando assim CharSequence). No entanto, String.replaceAll()não é restrito substituindo apenas caracteres seqüenciais. Você pode substituir caracteres não sequenciais, desde que sua expressão regular seja construída dessa maneira.

Além disso (o mais importante e dolorosamente óbvio), replace()só pode substituir valores literais; Considerando que replaceAllpode substituir sequências 'like' (não necessariamente idênticas).

hfontanez
fonte
-1

replace()O método não usa o padrão regex, enquanto o replaceAll()método usa o padrão regex. Então replace()executa mais rápido que replaceAll().

um homem
fonte
3
isso não é verdade. Se você olhar para a fonte de substituir você vai ver que também usou o padrão e Matcher (ie regex)
xtrakBandit
-5

replace funciona no tipo de dados char, mas replaceAll funciona no tipo de dados String e ambos substituem todas as ocorrências do primeiro argumento pelo segundo argumento.

Pramod Kumar
fonte