2013-06-28 13 views
13

Sprawdziłem w Java API i niektórych popularnych bibliotekach innych firm, ale nie jestem w stanie znaleźć odpowiedniej metody, która zrobi to, co robi String.replaceAll, z wyjątkiem StringBuilder.replaceAll dla StringBuilder z obsługą regex?

Wiem, że przy odrobinie pracy można to zrobić dla StringBuffer, ale nie chcę iść tą drogą, ponieważ StringBuffer jest wolniejszy.

Czy ktoś wie o jakichkolwiek zewnętrznych aplikacjach lub czy jest szybki fragment kodu do wdrożenia tej funkcji?

+0

Czy to krytyczne działanie lub tak duży ciąg, który konwertuje go na ciąg znaków i zastępowanie (i jego konwersję w razie potrzeby) nie wchodzi w grę? – Dukeling

+1

Możesz stworzyć 'Matchera' (który można utworzyć na dowolnym' CharSequence'), a następnie napisać pętlę z 'appendReplacement' i' appendTail', aby napisać własny 'replaceAll'. –

+0

Tak, ale ten używa StringBuffer ... – h22

Odpowiedz

0

Apache Harmony Matcher source code wydaje się być w pełni nadający się do użycia z StringBuilder zamiast obecnie używanego, wystarczy przejść do innej paczki. Wydaje się, że nie pociąga za sobą wielu zależności. Licencja Apache znajdująca się na początku pliku może nie być zła nawet w przypadku projektu komercyjnego.

Kod może być ponownie użyty, ale licencja jest tam trudniejsza (musisz opublikować zmienioną wersję Matchera, ale prawdopodobnie nie całą resztę kodu). To samo dotyczy oryginalnej implementacji Sun, którą można znaleźć pod adresem here w projekcie OpenJDK.

3

String.replaceAll to tylko wygodna metoda dla Matcher.replaceAll. Matcher to "faktyczny" sposób korzystania z regex w Javie i pozwala na znacznie bardziej wyrafinowane przypadki użycia.

Co więcej, wszystko, co można zrobić za pomocą metod wyrażeń regularnych na String, można wykonać za pomocą podobnych metod na Matcher. Piękno jest, że praca z Matcher s więcej niż tylko String s: Matcher s można uzyskać za każdym CharSequence (interfejs, który jest realizowany przez StringBuilder, StringBuffer, String i CharBuffer). Więc może po prostu zrobić:

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")); 

wyjście będzie This works with StringBuilders.

Working demo.

+0

Nie jestem pewien, czy OP jest dla czegoś takiego, ponieważ 'm.relaceAll' będzie wewnętrznie używać StringBuffer i zwróci String z zastąpionymi danymi. Wierzę, że OP chce wiedzieć, czy istnieje sposób, aby użyć StringBuilder zamiast StringBuffer, jak używamy go w 'Matcher # appendReplacement()', ale mogę się mylić. Komentarz OP byłby lepszy tutaj. – Pshemo

+0

@Pshemo ah okej, nie wiedziałem, że 'Matcher' używa wewnętrznie StringBuffer. –

+3

Zasadniczo mam następujący podpis metody: 'public void replaceAll (końcowy konstruktor StringBuilder, ostateczne wyrażenie regularne, ostateczna zamiana String)'. Dane budowniczego powinny zostać zmodyfikowane bez konieczności ponownego przypisywania. –

0

regexpa nie ma modyfikacji zmienny CharSequence wewnętrznie. Regex analizuje numer CharSequence, aby zwrócić wartość String, gdzie wynikiem jest String. StringBuffer jest wyjątkiem, ponieważ istnieje specjalna obsługa - tak jak w przypadku StringBuilder jest , musisz zmodyfikować go z wynikiem meczu.

Co można zrobić, zamiast:

// 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>")); 
} 

View a test code demo!