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

ReplaceAll для StringBuilder с поддержкой регулярных выражений?

Я просмотрел API Java и некоторые распространенные сторонние библиотеки, но я не могу найти подходящий метод, который будет делать то, что делает String.replaceAll, за исключением StringBuilder.

Я знаю, что с небольшой работой это можно сделать для StringBuffer, но я не хочу идти по этой дороге, потому что StringBuffer работает медленнее.

Кто-нибудь знает какие-либо сторонние утилиты, или если есть быстрый фрагмент кода для реализации этой функции?

4b9b3361

Ответ 1

String.replaceAll является просто методом удобства для Matcher.replaceAll. Matcher - это "реальный" способ использования регулярного выражения в Java и позволяет использовать гораздо более сложные варианты использования.

Кроме того, все, что можно сделать с помощью методов regex на String, можно выполнить с помощью аналогичных методов на Matcher. Красота заключается в том, что Matcher работает с более чем String s: Matcher может быть получена для любого CharSequence (интерфейс, который реализуется StringBuilder, StringBuffer, String и CharBuffer). Поэтому вы можете просто:

import java.util.regex.*;

...

StringBuilder sb = new StringBuilder();
sb.append("This works with StringBuffers");
Pattern p = Pattern.compile("\\Buffer\\B");
Matcher m = p.matcher(sb);
System.out.println(m.replaceAll("uilder"));

Выведет This works with StringBuilders.

Рабочая демонстрация.

Ответ 2

Я не хочу идти по этому пути, потому что StringBuffer работает медленнее.

Правда, но с обычной преждевременной оптимизацией, а главное, современные JVMs используют escape-анализ для удаления блокировок StringBuffer/Vector/HashTable в некоторых случаях, поэтому, как только эта оптимизация произойдет, производительность будет примерно одинаковой.

Ответ 3

Apache Harmony Исходный код для сопоставления кажется полностью переработанным для использования с StringBuilder вместо используемого в настоящее время StringBuffer, просто перейдите к другой упаковка. Кажется, он не затягивает с ним много зависимостей. Лицензия Apache, которая находится в начале файла, может быть неэффективной даже для коммерческого проекта.

Код пути GNU Classpath также можно использовать повторно, но там сложнее работать (вам нужно опубликовать измененную версию Matcher, но, возможно, остальная часть вашего кода). То же самое касается исходной реализации Sun, которую можно найти здесь в проекте OpenJDK.

Ответ 4

Regex не модифицирует изменчивый CharSequence внутри. Regex анализирует a CharSequence для возврата a String, где String - результат. StringBuffer является исключением, так как существует специальная обработка, так как для StringBuilder является CharSequence, вы должны изменить его с результатом соответствия.

Что вы можете сделать вместо этого:

// Class
private static final Pattern MY_PATTERN = Pattern.compile("my|regex");

{ // Method
    StringBuilder builder;
    // ...

    Matcher m = MY_PATTERN.matcher(builder);
    builder.replace(0, builder.length(), m.replaceAll("<b>$0</b>"));
}

Просмотр демонстрации тестового кода!