Differenza tra String replace () e replaceAll ()


221

Qual è la differenza tra java.lang.String replace()e replaceAll()metodi, oltre a usare successivamente regex? Per le sostituzioni semplici come, sostituire .con / , c'è qualche differenza?

Risposte:


174

In java.lang.String, il replacemetodo prende una coppia di caratteri o una coppia di CharSequence(di cui String è una sottoclasse, quindi prenderà felicemente un paio di stringhe). Il replacemetodo sostituirà tutte le occorrenze di un carattere o CharSequence. D'altra parte, entrambi gli Stringargomenti replaceFirste replaceAllsono espressioni regolari (regex). L'uso di una funzione errata può portare a bug sottili.


30
Inoltre, secondo i documenti java, ogni chiamata a str.replaceAll(regex, repl)è uguale a Pattern.compile(regex).matcher(str).replaceAll(repl). Quindi c'è un grande sovraccarico a seconda di quanto viene utilizzato.
user845279

4
@ user845279 È interessante dire che dal momento che String#replace(target, replacement)fa la stessa cosa, tranne che cita le stringhe: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));c'è qualche motivo per cui String#replacesarebbe più veloce di String#replaceAll? Non sembrerebbe così poiché String#replaceesegue solo operazioni aggiuntive.
Horsey

1
Solo curioso, in questa risposta dov'è il confronto esplicito contro replaceAll. La risposta è più sureplace
Manuel Jordan,

questo significa che replAll () sarebbe più costoso a causa della corrispondenza regex?
meraviglia

98

D: Qual è la differenza tra i java.lang.Stringmetodi replace()e replaceAll(), a parte questo, in seguito utilizza regex.

A: Solo la regex. Entrambi sostituiscono tutti :)

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

PS:

C'è anche un replaceFirst()(che richiede una regex)


1
Grazie per il chiarimento che è solo la regex. Come vorrei che lo avessero chiamato sostituireWithRegex () invece di replaceAll ()
HopeKing

Chiarimento: replaceAll () funziona con espressioni regolari, replace () funziona con CharSequence
Johnny Five

2
@JohnnyFive Questo lo rende più confuso. L'espressione regolare non è un tipo, lo CharSequenceè. Entrambi replace()e replaceAll()"lavorare con CharSequence". È che replaceAll()considera il dato CharSequencecome un'espressione regolare in modo da cercare corrispondenze regex , mentre replace()considera il dato CharSequencecome un semplice testo di ricerca in modo da cercare le occorrenze di esso.
SantiBailors,

43

Entrambi replace()e replaceAll()sostituiscono tutte le occorrenze nella stringa.

Esempi

Trovo sempre esempi utili per comprendere le differenze.

replace()

Utilizzare replace()se si desidera solo sostituire alcuni charcon un altro charo alcuni Stringcon un altro String(in realtà CharSequence).

Esempio 1

Sostituisci tutte le occorrenze del personaggio 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_

Esempio 2

Sostituisci tutte le occorrenze della stringa 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()

Utilizzare replaceAll()se si desidera utilizzare un modello di espressione regolare .

Esempio 3

Sostituisci qualsiasi numero 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

Esempio 4

Rimuovi tutti gli spazi bianchi.

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

Guarda anche

Documentazione

Espressioni regolari


34

Il replace()metodo è sovraccarico per accettare sia un argomento primitivo charche uno CharSequenceas.

Ora, per quanto riguarda le prestazioni, il replace()metodo è un po 'più veloce rispetto al replaceAll()fatto che quest'ultimo compila prima il modello regex e poi abbina prima di infine sostituire, mentre il primo corrisponde semplicemente per l'argomento fornito e sostituisce.

Poiché sappiamo che la corrispondenza del pattern regex è un po 'più complessa e di conseguenza più lenta, si consiglia di preferire replace()over replaceAll()ogni volta che è possibile.

Ad esempio, per sostituzioni semplici come quelle menzionate, è meglio usare:

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

invece di:

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

Nota: gli argomenti del metodo di conversione sopra indicati dipendono dal sistema.


6
Anche la sostituzione fa lo stesso, From java String docs :: public String replace (destinazione CharSequence, sostituzione CharSequence) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (replacement.toString ())); }
Prateek,

@Prateek: dopo jdk8, String :: replace non utilizza più Pattern: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , lo stesso in jdk11.
Franck,

D'accordo, in Java 8 praticamente entrambi i metodi sono quasi gli stessi, poiché entrambi appaiono il Pattern.compile(...)contenuto / parte nelle loro implementazioni, sembra replacemeno complesso su come definire / inviare il primo argomento. Non richiede "\". Inoltre replaceè disponibile da Java 1.5e da replaceAllallora1.4
Manuel Jordan,

3
String replace(char oldChar, char newChar)

Restituisce una nuova stringa risultante dalla sostituzione di tutte le occorrenze di oldChar in questa stringa con newChar.

String replaceAll(String regex, String replacement

Sostituisce ogni sottostringa di questa stringa che corrisponde all'espressione regolare fornita con la sostituzione fornita.


3
  1. Sostituire () e replaceAll () accetta due argomenti e sostituisce tutte le occorrenze della prima sottostringa (primo argomento) in una stringa con la seconda sottostringa (secondo argomento).
  2. replace () accetta una coppia di caratteri o charsequence e replaceAll () accetta una coppia di regex.
  3. Non è vero che sostituisca () funziona più velocemente di replAll () poiché entrambi utilizzano lo stesso codice nella sua implementazione

    Pattern.compile (regex) .matcher (questo) .ReplaceAll (sostituzione);

Ora la domanda è quando usare sostituire e quando usare sostituire All (). Quando si desidera sostituire una sottostringa con un'altra sottostringa, indipendentemente dal luogo di occorrenza nella stringa, utilizzare replace (). Ma se hai delle preferenze o condizioni particolari come sostituire solo quelle sottostringhe all'inizio o alla fine di una stringa, usa replaceAll (). Ecco alcuni esempi per dimostrare il mio 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?"

4
Non sono esattamente la stessa implementazione. replacenon chiama Pattern.compile(regex).matcher(this).replaceAll(replacement);. ChiamaPattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils

replaceAll () accetta una coppia di regex Perché sia ​​la stringa di ricerca sia la stringa di sostituzione sarebbero una regex? Con cosa verrebbero sostituiti gli eventi? Con una regex? Ovviamente solo il primo argomento è una regex (la stringa di ricerca). Il secondo non è un regex (la stringa di sostituzione).
SantiBailors,

1

Come accennato nella risposta di wickeD, con replaceAll la stringa di sostituzione viene gestita in modo diverso tra replace e replaceAll. Mi aspettavo che [3] e [4] avessero lo stesso valore, ma sono diversi.

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());
    }
}

L'output di questo è:

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

Questo è diverso da perl dove la sostituzione non richiede il livello extra di fuga:

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

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

che stampa \ X 2

Questo può essere piuttosto fastidioso, come quando si tenta di utilizzare il valore restituito da java.sql.DatabaseMetaData.getSearchStringEscape () con replaceAll ().


0

Vecchio thread lo so, ma sono un po 'nuovo di Java e scopro una delle sue cose strane. ho usatoString.replaceAll() ma ottengo risultati imprevedibili.

Qualcosa del genere rovina la stringa:

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

Quindi ho progettato questa funzione per aggirare lo strano 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;
}

Che ti rendono in grado di fare:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );

1
String.replaceAll()si aspetta espressioni regolari non argomenti letterali, motivo per cui si ottengono risultati "imprevedibili" (che sono davvero molto prevedibili). String.replace()funziona come vuoi tu.
Nadar,

Come regola empirica per quando otteniamo risultati inaspettati da Java, piuttosto che progettare una nuova funzione per aggirare ciò, è meglio supporre che quei risultati siano perfettamente corretti e che stiamo fraintendendo la funzionalità Java che stiamo usando.
SantiBailors,

0

Aggiungere alla "Migliore risposta" già selezionata (e altre altrettanto buone come quelle di Suragch), String.replace()è vincolato sostituendo i caratteri sequenziali (prendendo così CharSequence). Tuttavia, String.replaceAll()non è vincolato dalla sostituzione dei soli caratteri sequenziali. Puoi sostituire i caratteri non sequenziali purché la tua espressione regolare sia costruita in questo modo.

Inoltre (cosa più importante e dolorosamente ovvia), replace()può solo sostituire i valori letterali; mentre replaceAllpuò sostituire sequenze "simili" (non necessariamente identiche).


-1

replace()il metodo non usa il modello regex mentre il replaceAll()metodo usa il modello regex. Quindi replace()esegue più velocemente di replaceAll().


3
non è vero. Se guardi la fonte di sostituzione vedrai che ha usato anche Pattern and Matcher (cioè regex)
xtrakBandit

-5

sostituisce funziona con il tipo di dati char ma sostituisce Tutto funziona con il tipo di dati String ed entrambi sostituiscono tutte le occorrenze del primo argomento con il secondo argomento.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.