ChatGPT解决这个技术问题 Extra ChatGPT

Difference between String replace() and replaceAll()

What's the difference between java.lang.String 's replace() and replaceAll() methods, other than later uses regex? For simple substitutions like, replace . with / , is there any difference?


x
x-yuri

In java.lang.String, the replace method either takes a pair of char's or a pair of CharSequence's (of which String is a subclass, so it'll happily take a pair of String's). The replace method will replace all occurrences of a char or CharSequence. On the other hand, the first String arguments of replaceFirst and replaceAll are regular expressions (regex). Using the wrong function can lead to subtle bugs.


In addition, according to java docs, each call to str.replaceAll(regex, repl) is same as Pattern.compile(regex).matcher(str).replaceAll(repl). So there is a big overhead depending on how much it's used.
@user845279 It's interesting you would say that since String#replace(target, replacement) does the same thing, except it quotes the strings: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString())); Is there some reason why String#replace would be faster than String#replaceAll? It wouldn't seem like it since String#replace just performs additional operations.
Just curious, in this answer where is the explicit comparison against replaceAll. The answer is more about replace
this means replaceAll() would be costlier due to regex match?isn't it ?
M
Manuel Jordan

Q: What's the difference between the java.lang.String methods replace() and replaceAll(), other than that the latter uses regex.

A: Just the regex. They both replace all :)

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

PS:

There's also a replaceFirst() (which takes a regex)


Thx for the clarification that it is just the regex. How i wish they had named it replaceWithRegex() instead of replaceAll()
Clarification: replaceAll() works with regular expressions, replace() works with CharSequence
@JohnnyFive That makes it more confusing. Regular expression is not a type, CharSequence is. Both replace() and replaceAll() "work with CharSequence". It's that replaceAll() considers the given CharSequence as a regular expression so it looks for regex matches, while replace() considers the given CharSequence as a plain search text so it looks for occurrences of it.
both replace All ! thats what i wanted to hear !
S
Suragch

Both replace() and replaceAll() replace all occurrences in the String.

Examples

I always find examples helpful to understand the differences.

replace()

Use replace() if you just want to replace some char with another char or some String with another String (actually CharSequence).

Example 1

Replace all occurrences of the character x with 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_

Example 2

Replace all occurrences of the string fish with 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() if you want to use a regular expression pattern.

Example 3

Replace any number with an 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

Example 4

Remove all whitespace.

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

See also

Documentation

replace(char oldChar, char newChar)

replace(CharSequence target, CharSequence replacement)

replaceAll(String regex, String replacement)

replaceFirst(String regex, String replacement)

Regular Expressions

Tutorial

List of patterns


E
Eduardo Dennis

The replace() method is overloaded to accept both a primitive char and a CharSequence as arguments.

Now as far as the performance is concerned, the replace() method is a bit faster than replaceAll() because the latter first compiles the regex pattern and then matches before finally replacing whereas the former simply matches for the provided argument and replaces.

Since we know the regex pattern matching is a bit more complex and consequently slower, then preferring replace() over replaceAll() is suggested whenever possible.

For example, for simple substitutions like you mentioned, it is better to use:

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

instead of:

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

Note: the above conversion method arguments are system-dependent.


Even replace also do the same, 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: after jdk8, String::replace is not using Pattern anymore : hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , same in jdk11.
Agree, In Java 8 practically both methods are almost the same, for both appear the Pattern.compile(...) content/part in their implementations, seems replace is less complex about how to define/send the first argument. It does not require "\" . Furthermore replace is available since Java 1.5 and replaceAll since 1.4
A
Aarya

Both replace() and replaceAll() accepts two arguments and replaces all occurrences of the first substring(first argument) in a string with the second substring (second argument). replace() accepts a pair of char or charsequence and replaceAll() accepts a pair of regex. It is not true that replace() works faster than replaceAll() since both uses the same code in its implementation Pattern.compile(regex).matcher(this).replaceAll(replacement);

Now the question is when to use replace and when to use replaceAll(). When you want to replace a substring with another substring regardless of its place of occurrence in the string use replace(). But if you have some particular preference or condition like replace only those substrings at the beginning or end of a string use replaceAll(). Here are some examples to prove my 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?"

They are not the exact same implementation. replace doesn't call Pattern.compile(regex).matcher(this).replaceAll(replacement);. It calls Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
replaceAll() accepts a pair of regex Why would both the search string and the replacement string be a regex? What would the occurrences be replaced with? With a regex? Of course only the first argument is a regex (the search string). The second one is not a regex (the replacement string).
K
Kampai
String replace(char oldChar, char newChar)

Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.

String replaceAll(String regex, String replacement

Replaces each substring of this string that matches the given regular expression with the given replacement.


K
KnockingHeads

To throw more light with an example into how both are going to work for below code:

public static void main(String[] args)
{
    String s = "My\\s aaab\\s is\\s aaab\\s name";
    String s1 = s.replace("\\s", "c");
    System.out.println(s1);
    String s2 = s.replaceAll("\\s", "c");
    System.out.println(s2);
}

Output:

Myc aaabc isc aaabc name
My\scaaab\scis\scaaab\scname

Explanation

s.replace replaces "\\s" sequence of characters with c. Hence, the output in first line. s.replaceAll considers \\s as a regex rather(equivalent to space) and replaces spaces with c. \\s in String s is escaped with first \ encountered and becomes \s.

Intellij Idea is smart enough to notify you of the usage as well. If you take a closer look at below image, you will see the difference in interpretation by Intellij idea for replace and replaceAll usage.

https://i.stack.imgur.com/ICXW7.png


C
Codebeat

Old thread I know but I am sort of new to Java and discover one of it's strange things. I have used String.replaceAll() but get unpredictable results.

Something like this mess up the string:

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

So I designed this function to get around the weird problem:

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

Which make you able to do:

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

String.replaceAll() expects regular expressions not literal arguments, which is why you get "unpredictable" (which are really very much predictable) results. String.replace() works the way you want.
As a rule of thumb for when we get unexpected results from Java, rather than designing a new function to get around that, it's better to assume that those results are dead right and that we are misunderstanding the Java functionality we are using.
I understand that replaceAll uses regex .. but this simple function strReplace fixed my issue.
K
Keith Crews

As alluded to in wickeD's answer, with replaceAll the replacement string is handled differently between replace and replaceAll. I expected a[3] and a[4] to have the same value, but they are different.

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

The output of this is:

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

This is different from perl where the replacement does not require the extra level of escaping:

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

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

which prints \X 2

This can be quite a nuisance, as when trying to use the value returned by java.sql.DatabaseMetaData.getSearchStringEscape() with replaceAll().


c
chiperortiz

From Java 9 there is some optimizations in replace method.

In Java 8 it uses a regex.

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

From Java 9 and on.

https://i.stack.imgur.com/TMb7B.png

And Stringlatin implementation.

https://i.stack.imgur.com/7RW94.png

Which perform way better.

https://medium.com/madhash/composite-pattern-in-a-nutshell-ad1bf78479cc?source=post_internal_links---------2------------------


j
justcurious

replace() method doesn't uses regex pattern whereas replaceAll() method uses regex pattern. So replace() performs faster than replaceAll().


thats not true. If you look at the source of replace you will see it also used the Pattern and Matcher (ie regex)
From Java 9 this is true.
h
hfontanez

To add to the already selected "Best Answer" (and others that are just as good like Suragch's), String.replace() is constrained by replacing characters that are sequential (thus taking CharSequence). However, String.replaceAll() is not constrained by replacing sequential characters only. You could replace non-sequential characters as well as long as your regular expression is constructed in such a way.

Also (most importantly and painfully obvious), replace() can only replace literal values; whereas replaceAll can replace 'like' sequences (not necessarily identical).


P
Pramod Kumar

replace works on char data type but replaceAll works on String datatype and both replace the all occurrences of first argument with second argument.