Заменить все вхождения подстроки в строке - что более эффективно в Java?
Я знаю два способа замены всех вхождений подстроки в строке.
Способ регулярного выражения (при условии, что "подстрока, подлежащая замене" не включает специальные символы регулярного выражения):
String regex = "substring-to-be-replaced" + "+";
Pattern scriptPattern = Pattern.compile(regex);
Matcher matcher = scriptPattern.matcher(originalstring);
newstring = matcher.replaceAll("replacement-substring");
Путь String.replace():
newstring = originalstring.replace("substring-to-be-replaced", "replacement-substring");
Что из двух более эффективно (и почему)?
Существуют ли более эффективные способы, чем описанные выше два?
5 ответов
String.replace()
использует регулярное выражение внизу.
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL)
.matcher(this ).replaceAll(
Matcher.quoteReplacement(replacement.toString()));
}
Существуют ли более эффективные способы, чем описанные выше два?
Дано, что вы работаете с реализацией, поддерживаемой, например, массивом, а не неизменным классом String (поскольку string.replace
создает новую строку при каждом вызове). Смотрите, например, StringBuilder.replace ().
Компиляция регулярного выражения влечет за собой довольно много накладных расходов, что очевидно при наблюдении за исходным кодом Pattern. К счастью, Apache предлагает альтернативный подход в StringUtils.replace()
что в соответствии с исходным кодом (строка #3732) является довольно эффективным.
Вот исходный код из openjdk:
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
Вместо того, чтобы использовать string
s, которые являются неизменными, используют char
массивы или другой изменяемый тип (например, StringBuffer
или же StringBuilder
).
Не выполняя ни профилирования, ни бенчмаркинга, я бы сказал, что вполне безопасно сделать ставку на то, что если вам не нужна магия регулярных выражений, то это накладные расходы на анализатор регулярных выражений (который вы получите независимо от того, что с точки зрения памяти как а также использование процессора) стоит вам гораздо больше, чем вы можете получить на другом конце.
Разве вы не должны сравнивать заменить все 2 раза? Однако для одного вызова это вряд ли будет измеримо. И вы будете делать миллионы сравнений?
Тогда я ожидал бы, что 'compile' будет быстрее, но только если вы не используете константу String без каких-либо шаблонных правил.
Где проблема в написании микро-теста? Или посмотрите источник.