Представьте replaceAll в виде строки () по сравнению с Matcher replaceAll () (Различия в производительности)

Я полагаю, что сравнение nvarchars является более дорогостоящим, чем varchars, таким образом, это совершенно допустимо и даже предпочтительно в местах, где Вам действительно не нужны unicode возможности, т.е. для некоторых внутренних идентификаторов.

И затраты на хранение все еще действительно имеет значение . Если у Вас есть миллиарды строк тогда, те "небольшие" различия становятся большими довольно быстро.

44
задан Suvesh Pratapa 24 September 2009 в 06:44
поделиться

6 ответов

Согласно документации для String.replaceAll , о вызове метода говорится следующее:

Вызов этого метода форма str.replaceAll (регулярное выражение, repl) дает точно такой же результат, как и выражение

 Pattern.compile (регулярное выражение) .matcher (str) .replaceAll (repl)

Следовательно, можно ожидать, что производительность между вызовом String.replaceAll и явным созданием Matcher и Pattern должна быть одинаковой.

] Edit

Как было указано в комментариях, несуществующая разница в производительности будет верна для одного вызова replaceAll из String или Matcher , однако, если нужно выполнить несколько вызовов replaceAll , можно ожидать, что будет полезно сохранить скомпилированный шаблон , поэтому относительно дорогостоящая компиляция шаблона регулярного выражения не нужно выполнять каждый раз.

75
ответ дан 26 November 2019 в 21:46
поделиться

Исходный код String.replaceAll () :

public String replaceAll(String regex, String replacement) {
    return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

Он должен сначала скомпилировать шаблон - если вы собираетесь запускать его много раз с одним и тем же шаблоном на коротких строках производительность будет намного выше, если вы повторно используете один скомпилированный шаблон.

23
ответ дан 26 November 2019 в 21:46
поделиться

Основное отличие состоит в том, что если вы удерживаете шаблон , используемый для создания Matcher , вы можете избежать повторной компиляции регулярного выражения каждый раз, когда вы его используете. . Проходя через String , вы не получаете возможности «кэшировать», как это.

Если у вас каждый раз другое регулярное выражение, используйте String класс replaceAll в порядке. Если вы применяете одно и то же регулярное выражение ко многим строкам, создайте один Pattern и повторно используйте его.

9
ответ дан 26 November 2019 в 21:46
поделиться

Неизменяемость / безопасность потоков: скомпилированные шаблоны неизменяемы, сопоставители - нет. (см. Является ли Java Regex Thread Safe? )

Обработка пустых строк: replaceAll должен корректно обрабатывать пустые строки (это не соответствует шаблону пустой входной строки)

Приготовление кофе и т. д .: последний Я слышал, что ни String, ни Pattern, ни Matcher не имеют для этого каких-либо функций API.

edit: что касается обработки NULL, документация для String и Pattern явно не говорит об этом, но я подозреваю, что они вызовут исключение NullPointerException, поскольку они ожидать String.

6
ответ дан 26 November 2019 в 21:46
поделиться

Реализация String.replaceAll сообщает вам все, что вам нужно знать:

return Pattern.compile(regex).matcher(this).replaceAll(replacement);

(И документы говорят то же самое.)

Пока я не знаю ' t проверил кеширование, я бы конечно ожидал, что компиляция шаблона один раз и сохранение статической ссылки на него будет более эффективным, чем вызов Pattern.compile с тем же шаблоном каждый раз. Если есть кэш, это будет небольшая экономия эффективности - если его нет, то он может быть большим.

4
ответ дан 26 November 2019 в 21:46
поделиться

Разница в том, что String.replaceAll () компилирует регулярное выражение при каждом его вызове. Нет эквивалента для статического метода Regex.Replace () .NET, который автоматически кэширует скомпилированное регулярное выражение. Обычно replaceAll () - это то, что вы делаете только один раз, но если вы собираетесь вызывать его повторно с одним и тем же регулярным выражением, особенно в цикле, вам следует создать объект Pattern и использовать метод Matcher.

Вы можете также заранее создайте Matcher и используйте его метод reset () для перенацеливания его при каждом использовании:

Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
  System.out.println(m.reset(s).replaceAll(repl));
}

Выигрыш в производительности от повторного использования Matcher, конечно, нигде не так велик, как от повторного использования Pattern.

4
ответ дан 26 November 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: