Подтвердить что ты не робот

Самый быстрый способ выполнить много строк в Java

Мне нужно написать какой-то парсер, который получает String и заменяет некоторые наборы символов другими. Код выглядит следующим образом:

noHTMLString = noHTMLString.replaceAll("</p>", "\n");
noHTMLString = noHTMLString.replaceAll("<br/>", "\n\n");
noHTMLString = noHTMLString.replaceAll("<br />", "\n\n");
//here goes A LOT of lines like these ones

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

Я прочитал некоторые темы здесь об использовании StringBuilder в качестве альтернативы, но в нем отсутствует метод ReplaceAll и, как он отметил здесь Превосходит ли производительность string.replaceAll() неизменность строки? метод replaceAll в классе String работает с

Match Pattern и Matcher и Matcher.replaceAll() использует StringBuilder для хранения возвращаемого значения поэтому я не знаю, действительно ли переключение на StringBuilder сократит время выполнения заметок.

Знаете ли вы быстрый способ быстро заменить множество строк? У вас есть какие-либо советы по этой проблеме?

Спасибо.

EDIT. Мне нужно создать отчет с несколькими полями с текстом html. Для каждой строки я вызываю метод, который заменяет все теги html и специальные символы внутри этих строк. С полным отчетом для анализа всего текста требуется более 3 минут. Проблема в том, что я должен часто ссылаться на этот метод

4b9b3361

Ответ 1

Я обнаружил, что org.apache.commons.lang.StringUtils является самым быстрым, если вы не хотите беспокоиться с StringBuffer.

Вы можете использовать его следующим образом:
noHTMLString = StringUtils.replace(noHTMLString, "</p>", "\n");

Я тестировал производительность, это было более опасно, чем мое настраиваемое решение StrinBuffer, подобное предложению @extraneon.

Ответ 2

Похоже, что ваш синтаксический анализ HTML там, возможно, вы использовали стороннюю библиотеку вместо того, чтобы повторно изобретать колесо?

Ответ 3

Я согласен с Martijn в использовании готового решения вместо того, чтобы разбирать его самостоятельно - там множество вещей, встроенных в Java в пакет javax.xml. Оптимальным решением было бы использовать преобразование XSLT для замены, это выглядит как идеальный вариант использования. Однако это сложно.

Чтобы ответить на вопрос, рассмотрели ли вы использование библиотек регулярных выражений? Похоже, что у вас есть много разных вещей, которые вы хотите сопоставить, и замените их одним и тем же (\n или пустая строка). Используя регулярные выражения, вы можете быть выражением типа "<br>|<br/>|<br />" или даже более умным, например <br.*?>", чтобы создать объект-сопряжение, на котором вы можете вызвать replaceAll.

Ответ 4

Я полностью согласен с Мартином здесь. Выберите подходящий инструмент для задания.

Если ваш файл, однако, не является HTML, но содержит только некоторые маркеры HTML, вы можете немного ускорить процесс.

Во-первых, если какая-то часть ввода не содержит сменных элементов, подумайте о том, чтобы начать с чего-то вроде:

if (!input.contains('<')) {
    return input;
}

Во-вторых, рассмотрим регулярное выражение:

Pattern p = Pattern.compile( your_regex );

Не создавайте шаблон для каждой отдельной строки replaceAll, но пытайтесь их объединить (регулярное выражение имеет оператор OR) и пусть Pattern оптимизирует регулярное выражение. Используйте скомпилированный шаблон и не компилируйте его в каждом вызове, это довольно дорого.

Если регулярные выражения немного сложны, вы также можете сами реализовать более быстрый (но потенциально менее читаемый) механизм замены:

StringBuilder result = new StringBuilder(input.length();
for (int i=0; i < input.length(); i++) {
  char c = input.charAt(i);

  if ( c != '<' ) {
    continue;
  }

  int closePos = input.indexOf( '>', i);
  if (closePos == -1) {// not found
    result.append( input.substring(i, input.length());
    return result.toString();
  }
  i = closePos;
  String token = input.substring(i, closePos);
  if ( token.equals( "p/" ) {
    result.append("\\n");
  } else if (token.equals(...)) {
  } else if (...) {
  } 
}
return result.toString();

Это может иметь некоторые ошибки:)

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