Différence entre String replace () et replaceAll ()

221

Quelle est la différence entre les méthodes replace()et les replaceAll()méthodes de java.lang.String , autres que l'utilisation ultérieure de regex? Pour les substitutions simples comme, remplacer .par / , y a-t-il une différence?

Jijoy
la source

Réponses:

174

Dans java.lang.String, la replaceméthode prend soit une paire de caractères soit une paire de CharSequence(dont String est une sous-classe, donc elle prendra volontiers une paire de String). La replaceméthode remplacera toutes les occurrences d'un caractère ou CharSequence. D'un autre côté, les deux Stringarguments replaceFirstet replaceAllsont des expressions régulières (regex). Utiliser la mauvaise fonction peut conduire à des bugs subtils.

emilan
la source
30
De plus, selon les documents java, chaque appel à str.replaceAll(regex, repl)est identique à Pattern.compile(regex).matcher(str).replaceAll(repl). Il y a donc un gros frais généraux en fonction de la quantité utilisée.
user845279
4
@ user845279 Il est intéressant de dire que puisque String#replace(target, replacement)fait la même chose, sauf qu'il cite les chaînes: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));y a-t-il une raison pour laquelle ce String#replaceserait plus rapide que String#replaceAll? Il ne semblerait pas qu'il en soit ainsi puisqu'il String#replaceeffectue simplement des opérations supplémentaires.
Horsey
1
Juste curieux, dans cette réponse où est la comparaison explicite replaceAll. La réponse est plus surreplace
Manuel Jordan
cela signifie que replaceAll () serait plus coûteux en raison de la correspondance d'expression régulière, n'est-ce pas?
me demande
98

Q: Quelle est la différence entre les java.lang.Stringméthodes replace()et replaceAll(), à part cela, la dernière utilise regex.

R: Juste l'expression régulière. Ils remplacent tous les deux :)

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

PS:

Il y a aussi un replaceFirst()(qui prend une expression régulière)

paulsm4
la source
1
Merci de préciser que ce n'est que l'expression régulière. Comment je souhaite qu'ils l'aient nommé replaceWithRegex () au lieu de replaceAll ()
HopeKing
Clarification: replaceAll () fonctionne avec des expressions régulières, replace () fonctionne avec CharSequence
Johnny Five
2
@JohnnyFive Cela rend plus confus. L'expression régulière n'est pas un type, l' CharSequenceest. Les deux replace()et replaceAll()"travailler avec CharSequence". C'est qui replaceAll()considère le donné CharSequencecomme une expression régulière afin qu'il recherche des correspondances d' expression régulière , tandis que replace()le donné CharSequencecomme un texte de recherche simple afin qu'il en recherche les occurrences .
SantiBailors
43

Les deux replace()et replaceAll()remplacer toutes les occurrences dans la chaîne.

Exemples

Je trouve toujours des exemples utiles pour comprendre les différences.

replace()

À utiliser replace()si vous voulez simplement en remplacer certains charpar un autre charou certains Stringpar un autre String(en fait CharSequence).

Exemple 1

Remplacez toutes les occurrences du personnage xpar 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_

Exemple 2

Remplacez toutes les occurrences de la chaîne fishpar 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()

À utiliser replaceAll()si vous souhaitez utiliser un modèle d'expression régulière .

Exemple 3

Remplacez n'importe quel nombre par 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

Exemple 4

Supprimez tous les espaces.

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

Voir également

Documentation

Expressions régulières

Suragch
la source
34

La replace()méthode est surchargée pour accepter à la fois une primitive charet uneCharSequence comme arguments.

Maintenant, en ce qui concerne les performances, la replace()méthode est un peu plus rapide quereplaceAll() parce ce dernier compile d'abord le modèle d'expression régulière, puis correspond avant de finalement remplacer, tandis que le premier correspond simplement à l'argument fourni et le remplace.

Puisque nous savons que la correspondance de motif regex est un peu plus complexe et , par conséquent plus lent, puis préférant replace()plus replaceAll()est suggéré chaque fois que possible.

Par exemple, pour des substitutions simples comme vous l'avez mentionné, il est préférable d'utiliser:

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

au lieu de:

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

Remarque: les arguments de la méthode de conversion ci-dessus dépendent du système.

Surender Thakran
la source
6
Même replace aussi fait la même chose, From java String docs :: public String replace (CharSequence target, CharSequence replacement) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (replacement.toString ())); }
Prateek
@Prateek: après jdk8, String :: replace n'utilise plus Pattern: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , même dans jdk11.
Franck
D'accord, en Java 8, les deux méthodes sont pratiquement les mêmes, car les deux apparaissent le Pattern.compile(...)contenu / la partie dans leurs implémentations, semble replacemoins complexe sur la façon de définir / envoyer le premier argument. Cela ne nécessite pas "\". De plus replaceest disponible depuis Java 1.5et replaceAlldepuis1.4
Manuel Jordan
3
String replace(char oldChar, char newChar)

Renvoie une nouvelle chaîne résultant du remplacement de toutes les occurrences de oldChar dans cette chaîne par newChar.

String replaceAll(String regex, String replacement

Remplace chaque sous-chaîne de cette chaîne qui correspond à l'expression régulière donnée par le remplacement donné.

S. Rahul
la source
3
  1. Replace () et replaceAll () acceptent tous deux deux arguments et remplacent toutes les occurrences de la première sous-chaîne (premier argument) dans une chaîne par la deuxième sous-chaîne (deuxième argument).
  2. replace () accepte une paire de caractères ou charsequence et replaceAll () accepte une paire de regex.
  3. Il n'est pas vrai que replace () fonctionne plus rapidement que replaceAll () car les deux utilisent le même code dans son implémentation

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

Maintenant, la question est de savoir quand utiliser replace et quand utiliser replaceAll (). Lorsque vous souhaitez remplacer une sous-chaîne par une autre sous-chaîne, quel que soit son lieu d'occurrence dans la chaîne, utilisez replace (). Mais si vous avez une préférence ou une condition particulière comme remplacer uniquement ces sous-chaînes au début ou à la fin d'une chaîne, utilisez replaceAll (). Voici quelques exemples pour prouver mon point:

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
la source
4
Ce ne sont pas exactement la même implémentation. replacen'appelle pas Pattern.compile(regex).matcher(this).replaceAll(replacement);. Il appellePattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils
replaceAll () accepte une paire d'expressions rationnelles Pourquoi la chaîne de recherche et la chaîne de remplacement seraient-elles une expression régulière? Avec quoi les occurrences seraient-elles remplacées? Avec une expression régulière? Bien sûr, seul le premier argument est une expression régulière (la chaîne de recherche). Le second n'est pas une expression régulière (la chaîne de remplacement).
SantiBailors
1

Comme mentionné dans la réponse de wickeD, avec replaceAll, la chaîne de remplacement est traitée différemment entre replace et replaceAll. Je m'attendais à ce qu'un [3] et un [4] aient la même valeur, mais ils sont différents.

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

La sortie de ceci est:

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

Ceci est différent de perl où le remplacement ne nécessite pas le niveau supplémentaire d'échappement:

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

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

qui imprime \ X 2

Cela peut être assez gênant, comme lorsque vous essayez d'utiliser la valeur renvoyée par java.sql.DatabaseMetaData.getSearchStringEscape () avec replaceAll ().

Keith Crews
la source
0

Vieux fil que je connais mais je suis un peu nouveau pour Java et découvre une de ses choses étranges. j'ai utiliséString.replaceAll() mais j'obtiens des résultats imprévisibles.

Quelque chose comme ça gâche la chaîne:

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

J'ai donc conçu cette fonction pour contourner l'étrange problème:

//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;
}

Ce qui vous permet de faire:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );
Codebeat
la source
1
String.replaceAll()attend des expressions régulières et non des arguments littéraux, c'est pourquoi vous obtenez des résultats "imprévisibles" (qui sont vraiment très prévisibles). String.replace()fonctionne comme vous le souhaitez.
Nadar
En règle générale, lorsque nous obtenons des résultats inattendus de Java, plutôt que de concevoir une nouvelle fonction pour contourner cela, il est préférable de supposer que ces résultats sont tout à fait exacts et que nous comprenons mal la fonctionnalité Java que nous utilisons.
SantiBailors
0

Ajouter à la "meilleure réponse" déjà sélectionnée (et à d'autres qui sont tout aussi bonnes que celle de Suragch), String.replace()est contraint en remplaçant les caractères qui sont séquentiels (prenant ainsi CharSequence). Cependant, String.replaceAll()n'est pas contraint en remplaçant uniquement les caractères séquentiels. Vous pouvez remplacer les caractères non séquentiels aussi longtemps que votre expression régulière est construite de cette manière.

De plus (le plus important et le plus douloureusement évident), replace()ne peut que remplacer les valeurs littérales; tandis que replaceAllpeut remplacer des séquences «similaires» (pas nécessairement identiques).

hfontanez
la source
-1

replace()la méthode n'utilise pas de motif regex alors que la replaceAll()méthode utilise le motif regex. Effectue donc replace()plus rapidement que replaceAll().

un homme
la source
3
ce n'est pas vrai. Si vous regardez la source du remplacement, vous verrez qu'il a également utilisé le Pattern and Matcher (ie regex)
xtrakBandit
-5

replace fonctionne sur le type de données char mais replaceAll fonctionne sur le type de données String et les deux remplacent toutes les occurrences du premier argument par le deuxième argument.

Pramod Kumar
la source