Java String.replace () против String.replaceFirst () против доморощенного - PullRequest
5 голосов
/ 02 октября 2010

У меня есть класс, который много обрабатывает текст. Для каждой строки длиной от 100 до 2000 символов выполняется 30 различных замен строк.

Пример:

string modified;
for(int i = 0; i < num_strings; i++){
 modified = runReplacements(strs[i]);
 //do stuff
}

public runReplacements(String str){
  str = str.replace("foo","bar");
  str = str.replace("baz","beef");
  ....
  return str;
}

'foo', 'baz' и все остальные "цели" должны появляться только один раз и являются строковыми литералами (нет необходимости в фактическом регулярном выражении).

Как вы понимаете, меня беспокоит производительность :) 1008 *

Учитывая это,

  • replaceFirst() кажется плохим выбором, поскольку он не будет использовать Pattern.LITERAL и будет выполнять дополнительную обработку, которая не требуется.

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

Кроме того, поскольку мои замещающие тексты всегда одинаковы, мне кажется, имеет смысл написать свой собственный код, иначе String.replaceFirst() или String.replace() будут выполнять Pattern.compile каждый раз в фоновом режиме. Думая, что я должен написать свой собственный код, это моя мысль:

  • Выполните Pattern.compile() только один раз для каждой желаемой замены букв (не нужно перекомпилировать каждый раз) (т.е. p1 - p30)

  • Затем выполните следующие действия для каждого pX: p1.matcher(str).replaceFirst(Matcher.quoteReplacement("desiredReplacement"));

Таким образом, я отказываюсь от корабля при первой замене (вместо прохождения всей строки) и использую литерал против regex , и я не делаю повтор компилировать каждую итерацию.

Итак, что лучше для производительности?

Ответы [ 3 ]

3 голосов
/ 02 октября 2010

Итак, что лучше для производительности?

Измерьте это!; -)

ETA: Поскольку ответ из двух слов звучит безвозвратно язвительно, я уточню немного.«Измерьте это и скажите нам ...», поскольку может быть какое-то общее практическое правило относительно эффективности различных подходов, которые вы цитируете (хорошие, все), но я не знаю об этомИ, как уже упоминалось в нескольких комментариях к этому ответу, различные подходы с большой вероятностью будут затоплены средой приложения.Итак, измерьте in vivo и сконцентрируйтесь на этом, если это реальная проблема.(И дайте нам знать, как это происходит ...)

2 голосов
/ 02 октября 2010

Во-первых, запустите и профилируйте все приложение с помощью простого соответствия / замены.Это может показать вам, что:

  • ваше приложение уже работает достаточно быстро, или
  • ваше приложение тратит большую часть своего времени на выполнение чего-то другого, поэтому оптимизация кода соответствия / замены не являетсястоит.

Предполагая, что вы определили, что сопоставление / замена является узким местом, напишите себе небольшое приложение для тестирования производительности, которое позволяет вам проверять производительность и правильность ваших алгоритмов-кандидатов на представительных входных данных.Это также хорошая идея, чтобы включить входные данные «крайний случай», которые могут вызвать проблемы;Например, для подстановок в вашем примере входные данные, содержащие последовательность «bazoo», могут быть крайним случаем.Что касается производительности, убедитесь, что вы избегаете ловушек Java-микробанчмаркинга;например, эффекты разогрева JVM.

Далее реализуем несколько простых альтернатив и опробуем их.Один из них достаточно хорош?Готово!

В дополнение к вашим идеям вы можете попробовать объединить поисковые термины в одно регулярное выражение (например, "(foo | baz)"), использовать Matcher.find(int), чтобы найти каждое вхождение, использовать HashMapдля поиска замещающих строк и StringBuilder для построения выходной строки из подстрок входных строк и замен.(Хорошо, это не совсем тривиально, и это зависит от эффективной обработки чередования шаблонов / совпадений ... но я не уверен, что так. Но именно поэтому вы должны тщательно сравнивать кандидатов.)

В(маловероятно, что IMO), когда простая альтернатива его не обрезает, на этой странице википедии есть некоторые сведения, которые могут помочь вам в реализации собственного эффективного сопоставления / замены.

0 голосов
/ 02 октября 2010

Разве это не расстраивает, когда вы задаете вопрос и получаете кучу советов, говорящих вам, чтобы вы проделали большую работу и выяснили это для себя ?!

Я говорю, используйте replaceAll ();

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

[править] PS. После этого вы можете измерить его.

[править 2] PPS. (и расскажите нам, что вы нашли)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...