String.replace: примеры (JAVA)
String.replace(char oldChar, char newChar): StringОбщее описание метода
В Java метод String.replace выполняет замену подстрок в строке и представлен двумя перегруженными версиями:
String replace(char oldChar, char newChar)- заменяет все вхождения символаoldCharна символnewChar.String replace(CharSequence target, CharSequence replacement)- заменяет все вхождения последовательности символовtargetнаreplacement. В реализации используется буквальное сравнение (без регулярных выражений).
Возвращаемое значение в обоих случаях - новая строка (String) с выполненными заменами. Исходная строка остается неизменной, поскольку String в Java неизменяем.
Особенности аргументов и поведения:
- Если
oldCharне найден, возвращается исходная строка (возможно тот же объект, оптимизация может вернуть тот же экземпляр). - Если
targetравен пустой строке, поведение у перегрузки сCharSequence- все места между символами и начало/конец считаются местами вхождения; замена вставитreplacementмежду символами (обычно такое поведение редко требуется). - Если аргумент
targetилиreplacementравенnull, генерируетсяNullPointerException. - Метод
replaceсCharSequenceработает по буквальному соответствию. Для шаблонных замен по регулярным выражениям служат методыreplaceAllиreplaceFirst, которые принимают regex. - Поддерживаются все реализации
CharSequence(например,StringBuilder,StringBuffer), они автоматически приводятся к строке при сравнении.
Резюме: String.replace подходит для простых буквальных замен символов или подстрок. Для регулярных выражений используются другие методы.
Короткие примеры использования
Примеры показывают код и результат.
1) Замена символов (char → char)
String s = "java";
String r = s.replace('a', 'o');
System.out.println(r);
jovo
2) Замена подстрок (CharSequence → CharSequence)
String s = "abracadabra";
String r = s.replace("abra", "x");
System.out.println(r);
xcadx
3) Если целевая подстрока отсутствует
String s = "hello";
String r = s.replace("z", "q");
System.out.println(r);
hello
4) Отличие от replaceAll (replace - буквальная замена, replaceAll - по regex)
String s = "a1b2";
String r1 = s.replace("\d", "#"); // буквальная замена \d не найдена
String r2 = s.replaceAll("\\d", "#"); // regex: цифры заменены
System.out.println(r1);
System.out.println(r2);
a1b2 a#b#
5) Передача CharSequence (например, StringBuilder)
StringBuilder sb = new StringBuilder("xx");
String s = "xx yy xx";
String r = s.replace(sb, new StringBuilder("zz"));
System.out.println(r);
zz yy zz
Аналоги и похожие методы в Java
Краткое перечисление альтернатив и их назначение.
String.replaceAll(String regex, String replacement)- замены по регулярному выражению; подходит при сложных шаблонах, но требует экранирования метасимволов.String.replaceFirst(String regex, String replacement)- заменяет только первое вхождение по regex.java.util.regex.PatternиMatcher- для сложных сценариев динамических замен и использования групп, доступа к MatchResult и поэтапного формирования строки сappendReplacement/appendTail.StringBuilder.replace(int start, int end, String str)- выполняет замену по индексам в изменяемом буфере; предпочтительнее при множественных по позициям изменениях ради производительности.- Apache Commons Lang
StringUtils.replace- удобные утилиты: безопаснее приnull, есть версии с заменой ограниченного числа вхождений.
Когда использовать что:
- Для простых буквальных замен -
String.replace. - Для шаблонных замен -
replaceAllилиMatcher. - Для больших или частых изменений -
StringBuilderили специализированные утилиты.
Аналоги в других языках и отличия
Короткие примеры для разных языков и ключевые отличия по сравнению с Java String.replace.
PHP - str_replace (буквально) и preg_replace (regex)
$s = 'abracadabra';
echo str_replace('abra', 'x', $s);
xcadx
JavaScript - String.prototype.replace (строка или RegExp)
let s = 'a1b2';
console.log(s.replace(/\d/g, '#')); // regex
console.log(s.replace('\d', '#')); // буквально, не заменяет цифры
a#b# a1b2
Python - str.replace(old, new[, count]) и re.sub
s = 'a1b2'
print(s.replace('1', 'X')) # буквальная
import re
print(re.sub(r'\d', '#', s)) # regex
aXb2 a#b#
SQL - REPLACE(column, 'old', 'new') (буквально), некоторые СУБД поддерживают regexp_replace
-- пример в SQL
SELECT REPLACE('abracadabra', 'abra', 'x');
xcadx
C# - string.Replace(string oldValue, string newValue) (буквально) и перегрузки для char
string s = "hello";
Console.WriteLine(s.Replace('l', 'x'));
hexxo
Lua - string.gsub (по умолчанию поддерживает шаблоны Lua, не полноценный regex)
print((string.gsub('a1b2','%d','#')))
a#b# 2
Go - strings.Replace и strings.ReplaceAll
import "strings"
s := "a1b2"
fmt.Println(strings.ReplaceAll(s, "1", "X"))
aXb2
Kotlin - методы String.replace(oldValue, newValue) и String.replace(Regex, String) (совместимы с Java, есть дополнительные удобства).
val s = "abracadabra"
println(s.replace("abra", "x"))
xcadx
Отличия: в большинстве языков есть отдельные функции для буквальной и регулярной замены; в некоторых языках (C#, Kotlin) семантика очень близка к Java, в JS поведение зависит от того, передана ли строка или RegExp.
Типичные ошибки и их проявления
Частые ошибки при использовании и примеры их результатов.
1) Ожидание изменения исходной строки (ошибка: String неизменяем)
String s = "hello";
s.replace('l', 'x');
System.out.println(s);
hello
Комментарий: метод возвращает новую строку; нужно присвоить результат, если требуется сохранить замену.
2) NullPointerException при передаче null для CharSequence
String s = "abc";
String r = s.replace(null, "x");
Exception in thread "main" java.lang.NullPointerException
3) Путаница с регулярными выражениями (ожидание, что replace работает как regex)
String s = "a1b2";
System.out.println(s.replace("\\d", "#")); // буквально ищет "\d"
a1b2
4) Ошибки с метасимволами в replacement при replaceAll (замена использует $1 для групп)
String s = "user$home";
String r = s.replaceAll("\\$home", "\\$ROOT");
System.out.println(r);
java.lang.IllegalArgumentException: Illegal group reference
Решение: использовать Matcher.quoteReplacement для безопасного replacement.
5) Некорректная работа при пустой целевой подстроке
String s = "abc";
System.out.println(s.replace("", "X"));
XaXbXcX
Комментарий: вставка между символами, обычно не ожидаемое поведение.
Изменения и история
Ключевые факты о развитии метода:
- Перегрузка с
charприсутствует в Java с ранних версий; версия сCharSequenceпоявилась в более поздних релизах платформы и давно доступна в современных JDK. - В последних версиях Java не было принципиальных изменений в семантике
String.replace. Развитие функциональности шло в сторону улучшений API для регулярных выражений и классаMatcher, а также оптимизаций производительности в реализацииStringи JIT-компилятора. - Для динамических и контекстных замен рекомендуется использовать
MatcherсappendReplacementиappendTail, что является стабильным подходом во всех современных версиях.
Расширенные и редкие сценарии использования
Несколько более сложных примеров с пояснениями.
1) Динамическая замена по шаблону с обработкой групп (использование Matcher)
import java.util.regex.*;
String s = "John:30, Mary:25";
Pattern p = Pattern.compile("(\\w+):(\\d+)");
Matcher m = p.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String name = m.group(1);
String age = m.group(2);
m.appendReplacement(sb, name + "(" + age + ")");
}
m.appendTail(sb);
System.out.println(sb.toString());
John(30), Mary(25)
Пояснение: для составления результата с вычислениями используется appendReplacement.
2) Безопасная вставка текста, содержащего символы $ и \ (использование Matcher.quoteReplacement)
String s = "path: $HOME";
String repl = "C:\\Users\\Name";
String r = s.replaceAll("\\$HOME", Matcher.quoteReplacement(repl));
System.out.println(r);
path: C:\Users\Name
3) Замена перекрывающихся вхождений через lookahead (пример с 'ana' в 'banana')
String s = "banana";
String r = s.replaceAll("(?=(ana))ana", "X");
System.out.println(r);
bXna
Пояснение: стандартный поиск не всегда находит перекрывающиеся шаблоны; для этого применяются lookahead/lookbehind.
4) Массовые последовательные замены с высокой производительностью (использование StringBuilder)
String s = "a".repeat(10000) + "b";
// если нужно заменить множество разных фрагментов в цикле, эффективнее собрать результат в StringBuilder
StringBuilder sb = new StringBuilder(s);
int index = sb.indexOf("a");
while (index != -1) {
sb.setCharAt(index, 'x');
index = sb.indexOf("a", index + 1);
}
System.out.println(sb.substring(0, 5));
xxxxx
Комментарий: для большого количества замен по позициям изменение буфера эффективнее создания новых строк.
5) Замена шаблонов с условной логикой (через Matcher и вычисление replacement)
Pattern p = Pattern.compile("(\\d+)");
Matcher m = p.matcher("Prices: 100 200 300");
StringBuffer out = new StringBuffer();
while (m.find()) {
int v = Integer.parseInt(m.group(1));
m.appendReplacement(out, String.valueOf(v * 2));
}
m.appendTail(out);
System.out.println(out.toString());
Prices: 200 400 600
Пояснение: для арифметики и других вычислений на основе найденных групп используется итерация по совпадениям.