Производительность Java оптимизировать, заменяя одну строку другой, неоднократно

0

Im работает над расширением HttpServlet (плагином) для CMS, и его задачей является фильтрация ответа HTML.

В моем методе filterResponse я получаю запрошенный text/html в String, который является одним из трех параметров.

В частности, мне нужно выполнить поиск в html String для определенного шаблона URL и немного изменить его. Теперь это может быть тяжелая операция, когда в большом документе есть много ссылок, и я хочу как можно больше оптимизировать этот процесс.

Моя первая версия просто использовала метод replace("://www.", "://www-x1.") В String.

Затем в текущей версии я использую классы Matcher и Pattern. Пример кода:

@Override
public String filterResponse(HttpServletRequest request, String textHtml, String contentType) throws Exception {

   Pattern pattern = Pattern.compile("://www.");

   Matcher m = pattern.matcher(textHtml);
   String response = m.replaceAll("://www-x1.");

   .....
   .....

   return response;
}

В коде реального мира я предварительно компилирую шаблоны (Pattern) в статических полях и делаю то же самое со строками, которые сопоставляются.

Любые идеи о том, как сделать это быстрее? Возможно, конвертировать в объект DOM или какой-либо другой объект XML для ускорения запросов? И т.п.

  • 0
    Я думаю, что для одной замены (т.е. одной строки поиска, одной замены) это близко к оптимальному. Если вы делаете это многократно с разными строками, определенно есть способы оптимизировать его. Преобразование в DOM (и обратно) вряд ли будет быстрее.
  • 0
    Как вы сравниваете производительность ваших решений? Как быстро ваш первый подход по сравнению со вторым? Я бы догадался, что первый простой подход - самый быстрый.
Показать ещё 3 комментария
Теги:
optimization
string
performance

1 ответ

0
Лучший ответ

Прежде всего, вы используете сопоставление шаблонов, где у вас нет шаблона. Это не только расточительствование производительности, это ошибка. Для "://www." используемый в качестве образца, последняя точка соответствует любому символу.

Если вы хотите заменить простую String а не шаблон, вы можете использовать String.replace вместо String.replaceAll. Это исправляет ошибку и сохраняет все накладные расходы на создание Pattern и Matcher внутри.

Если вы хотите использовать Pattern.compile("://www.", Pattern.LITERAL) регулярных выражений, самым простым Pattern.compile("://www.", Pattern.LITERAL) является использование Pattern.compile("://www.", Pattern.LITERAL) чтобы прекратить интерпретацию специальных символов и разрешить использование алгоритма Boyer-Moore для всей последовательности. Это, однако, только окупится, если вы сможете сохранить и повторно использовать подготовленный шаблон.

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

static String replace(String source)
{// the pattern would be better off being re-usable stored in a static field
  final Pattern pattern = Pattern.compile("://www.", Pattern.LITERAL);
  final Matcher m = pattern.matcher(source);
  boolean result = m.find();
  if (result) {
      StringBuilder sb = new StringBuilder(source.length()+16);
      int p=0;
      do {
        sb.append(source, p, m.start()).append("://www-x1.");
        p=m.end();
      } while (m.find());
      sb.append(source, p, source.length());
      return sb.toString();
  }
  return source;
}

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

  • 0
    Впоследствии я увидел, что вы упоминали replace а не replaceAll в своем вопросе. Но знали ли вы о разнице? Переход от replace к регулярному выражению не является естественным выбором ...
  • 0
    Я не имею понятия о разнице в накладных расходах, должен признать. Итак, вы бы порекомендовали использовать самое простое решение, какой метод replace строк? Или разница маргинальная? Я объявляю объекты Pattern как статические конечные поля.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню