Разница между String replace () и replaceAll ()

221

В чем разница между java.lang.String replace()и replaceAll()методами, за исключением того, что позже используется регулярное выражение? Для простых замен, таких как, заменить .на / , есть ли разница?

Jijoy
источник

Ответы:

174

В java.lang.String, то replaceметод либо берет пару Чары или пару CharSequence«s (из которых строка является подклассом, так что это будет счастливо взять пару струны). replaceМетод заменит все вхождения полукокса или CharSequence. С другой стороны, оба Stringаргумента replaceFirstи replaceAllрегулярные выражения (регулярное выражение). Использование неправильной функции может привести к незначительным ошибкам.

emilan
источник
30
Кроме того, согласно Java-документам, каждый вызов to str.replaceAll(regex, repl)такой же, как Pattern.compile(regex).matcher(str).replaceAll(repl). Таким образом, есть большие накладные расходы в зависимости от того, сколько он используется.
user845279
4
@ user845279 Интересно, вы бы сказали, что поскольку String#replace(target, replacement)делает то же самое, за исключением того, что цитирует строки: Pattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));есть ли какая-то причина, почему String#replaceэто будет быстрее, чем String#replaceAll? Казалось бы, это не так, поскольку String#replaceпросто выполняет дополнительные операции.
Хорси
1
Просто любопытно, в этом ответе где явное сравнение с replaceAll. Ответ больше оreplace
Мануэль Джордан
это означает, что replaceAll () будет дороже из-за совпадения регулярных выражений?
чудо
98

Q: В чем разница между java.lang.Stringметодами replace()и replaceAll(), кроме того, что позже используется регулярное выражение?

A: Просто регулярное выражение. Они оба заменяют все :)

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

PS:

Там также replaceFirst()(который принимает регулярное выражение)

paulsm4
источник
1
Спасибо за разъяснение, что это просто регулярное выражение. Как бы я хотел, чтобы они назвали его replaceWithRegex () вместо replaceAll ()
HopeKing
Пояснение: replaceAll () работает с регулярными выражениями, replace () работает с CharSequence
Johnny Five
2
@JohnnyFive Это делает его более запутанным. Регулярное выражение не является типом, CharSequenceесть. Оба replace()и replaceAll()"работают с CharSequence". Это то, что replaceAll()рассматривает данное CharSequenceкак регулярное выражение, поэтому оно ищет совпадения с регулярным выражением , в то время как replace()рассматривает данное CharSequenceкак обычный текст поиска, поэтому оно ищет его вхождения .
SantiBailors
44

Обе replace()и replaceAll()заменить все вхождения в строке.

Примеры

Я всегда нахожу примеры полезными для понимания различий.

replace()

Используйте, replace()если вы просто хотите заменить некоторые charна другиеchar или некоторые Stringна другие String(на самом деле CharSequence).

Пример 1

Заменить все вхождения персонажа xна 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_

Пример 2

Заменить все вхождения строки fishна 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()

Используйте, replaceAll()если вы хотите использовать шаблон регулярного выражения .

Пример 3

Заменить любое число на 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

Пример 4

Удалить все пробелы.

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

Смотрите также

Документация

Регулярные выражения

Suragch
источник
34

replace()Метод перегружен , чтобы принять как примитивный charи в CharSequenceкачестве аргументов.

Теперь, что касается производительности, replace()метод немного быстрее, чемreplaceAll() тот, который последний сначала компилирует шаблон регулярного выражения, а затем сопоставляет его перед окончательной заменой, тогда как первый просто сопоставляет предоставленный аргумент и заменяет.

Поскольку мы знаем, что сопоставление с образцом регулярных выражений немного сложнее и, следовательно, медленнее, тогда, когда это возможно, предлагается предпочтение replace()перед replaceAll().

Например, для простых замен, как вы упомянули, лучше использовать:

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

вместо того:

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

Примечание: приведенные выше аргументы метода преобразования зависят от системы.

Сурендер Такран
источник
6
Даже замена также делает то же самое: Из java String docs :: public String replace (цель CharSequence, замена CharSequence) {return Pattern.compile (target.toString (), Pattern.LITERAL) .matcher (this) .replaceAll (Matcher.quoteReplacement (replacement.toString ())); }
Prateek
@Prateek: после jdk8 String :: replace больше не использует Pattern: hg.openjdk.java.net/jdk9/jdk9/jdk/file/65464a307408/src/… , то же самое в jdk11.
Франк
Согласитесь, в Java 8 практически оба метода практически одинаковы, так как оба появляются Pattern.compile(...)в своих реализациях, контент / часть кажется replaceменее сложным в том, как определить / отправить первый аргумент. Не требует "\". Кроме того replace, доступно с Java 1.5и replaceAllс тех пор1.4
Мануэль Джордан
3
String replace(char oldChar, char newChar)

Возвращает новую строку, полученную в результате замены всех вхождений oldChar в этой строке на newChar.

String replaceAll(String regex, String replacement

Заменяет каждую подстроку этой строки, которая соответствует данному регулярному выражению с данной заменой.

С. Рахул
источник
3
  1. И replace (), и replaceAll () принимают два аргумента и заменяют все вхождения первой подстроки (первого аргумента) в строке второй подстрокой (вторым аргументом).
  2. replace () принимает пару char или charsequence, а replaceAll () принимает пару регулярных выражений.
  3. Это не правда, что replace () работает быстрее, чем replaceAll (), так как оба используют один и тот же код в своей реализации

    Pattern.compile (регулярное выражение) .matcher (это) .replaceAll (замена);

Теперь вопрос в том, когда использовать замену, а когда использовать replaceAll (). Если вы хотите заменить подстроку на другую подстроку независимо от места ее появления в строке, используйте replace (). Но если у вас есть какое-то конкретное предпочтение или условие типа замены только тех подстрок в начале или конце строки, используйте replaceAll (). Вот несколько примеров, чтобы доказать мою точку зрения:

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
источник
4
Они не являются точно такой же реализацией. replaceне звонит Pattern.compile(regex).matcher(this).replaceAll(replacement);. Он звонитPattern.compile(target.toString(), Pattern.LITERAL).matcher(this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
ChiefTwoPencils
replaceAll () принимает пару регулярных выражений. Почему строка поиска и строка замены будут регулярными выражениями? Чем будут заменены события? С регулярным выражением? Конечно, только первый аргумент является регулярным выражением (строка поиска). Второй не является регулярным выражением (строка замены).
SantiBailors
1

Как упоминалось в ответе wickeD, с replaceAll строка замены обрабатывается по-разному для replace и replaceAll. Я ожидал, что [3] и [4] будут иметь одинаковое значение, но они различны.

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

Выход этого:

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

Это отличается от Perl, где замена не требует дополнительного уровня экранирования:

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

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

который печатает \ X 2

Это может быть довольно неприятно, например, при попытке использовать значение, возвращаемое java.sql.DatabaseMetaData.getSearchStringEscape () с replaceAll ().

Кит Крюс
источник
0

Старый поток я знаю, но я новичок в Java и обнаружил одну из странных вещей. я использовалString.replaceAll() но получаю непредсказуемые результаты.

Что-то вроде этого портит строку:

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

Поэтому я разработал эту функцию, чтобы обойти странную проблему:

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

Что позволяет вам делать:

sUrl=this.strReplace("./", "//", sUrl );
sUrl=this.strReplace( "//", "/", sUrl );
Codebeat
источник
1
String.replaceAll()ожидает регулярных выражений, а не буквальных аргументов, поэтому вы получаете «непредсказуемые» (которые на самом деле очень предсказуемые) результаты. String.replace()работает так, как вы хотите.
Надар
Как правило, когда мы получаем неожиданные результаты от Java, а не разрабатываем новую функцию, чтобы обойти это, лучше предположить, что эти результаты абсолютно верны и что мы неправильно понимаем функциональность Java, которую мы используем.
SantiBailors
0

Добавление к уже выбранному «Лучшему ответу» (и другим, которые так же хороши, как у Сурагча), String.replace()ограничено заменой последовательных символов (таким образом, принимая CharSequence). Однако String.replaceAll()не ограничивается заменой только последовательных символов. Вы можете заменить непоследовательные символы, если ваше регулярное выражение построено таким образом.

Также (что наиболее важно и мучительно очевидно) replace()может заменить только буквальные значения; тогда как replaceAllможет заменить «похожие» последовательности (не обязательно идентичные).

hfontanez
источник
-1

replace()Метод не использует шаблон регулярных выражений, тогда как replaceAll()метод использует шаблон регулярных выражений. Так replace()работает быстрее чем replaceAll().

мужчина
источник
3
это не правда. Если вы посмотрите на источник замены, то увидите, что он также использовал Pattern and Matcher (то есть regex)
xtrakBandit
-5

replace работает с типом данных char, но replaceAll работает с типом данных String, и оба заменяют все вхождения первого аргумента вторым аргументом.

Прамод Кумар
источник