2013-06-28 13 views
13

Ich habe in der Java-API und einigen gebräuchlichen Bibliotheken von Drittanbietern gesucht, aber ich kann keine geeignete Methode finden, die das tut, was String.replaceAll tut, außer für StringBuilder.replaceAll für StringBuilder mit Regex-Unterstützung?

Ich weiß, dass mit ein wenig Arbeit, kann es für StringBuffer getan werden, aber ich möchte nicht diesen Weg gehen, weil StringBuffer langsamer ist.

Kennt jemand Drittanbieter-Utilities oder gibt es einen schnellen Code, um diese Funktionalität zu implementieren?

+0

Ist es das Leistungskritische oder eine so große Zeichenkette, die es in eine Zeichenkette umwandelt und die Ersetzung durchführt (und sie zurückwandelt, falls erforderlich), kommt nicht in Frage? – Dukeling

+1

Sie können einen 'Matcher' erstellen (der auf einer beliebigen' CharSequence' erstellt werden kann) und dann eine Schleife mit 'appendReplacement' und' appendTail' schreiben, um Ihren eigenen 'replaceAll' zu schreiben. –

+0

Ja, aber dass man StringBuffer verwendet ... – h22

Antwort

0

Apache Harmony Matcher source code scheint vollständig nacharbeitbar zu sein mit StringBuilder anstelle der derzeit verwendeten StringBuffer verwendet werden, bewegen Sie sich einfach auf das andere Paket. Es scheint nicht viel Abhängigkeiten mit sich zu ziehen. Die Apache-Lizenz, die am Anfang der Datei steht, kann selbst für ein kommerzielles Projekt nicht schlecht sein.

GNU Classpath Code kann auch wiederverwendet werden, aber die Lizenz ist dort schwieriger (Sie müssen Ihre geänderte Version des Matcher veröffentlichen, aber wahrscheinlich nicht den Rest Ihres Codes). Gleiches gilt für die ursprüngliche Sun-Implementierung, die im OpenJDK-Projekt here gefunden werden kann.

3

String.replaceAll ist nur eine bequeme Methode für Matcher.replaceAll. Matcher ist die "tatsächliche" Art und Weise, Regex in Java zu verwenden und ermöglicht viel anspruchsvollere Anwendungsfälle.

Darüber hinaus kann alles, was mit Regex-Methoden auf String getan werden kann mit ähnlichen Methoden auf einem Matcher erfolgen. Die Schönheit ist, dass Matcher Arbeit mit mehr als nur String s: Matcher s kann für jede CharSequence (eine Schnittstelle, die von StringBuilder implementiert ist, StringBuffer, String und CharBuffer) erhalten werden. So können Sie einfach tun:

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

wird ausgegeben This works with StringBuilders.

Working demo.

+0

Ich bin nicht sicher, ob OP für so etwas ist, da 'm.relaceAll' intern StringBuffer verwendet und String mit ersetzten Daten zurückgibt. Ich glaube, dass OP wissen möchte, gibt es eine Möglichkeit, StringBuilder anstelle von StringBuffer zu verwenden, wie wir es in 'Matcher # appendReplacement()' verwenden, aber ich kann falsch liegen. OP-Kommentar wäre hier besser. – Pshemo

+0

@Phemo ah okay, ich wusste nicht, dass 'Matcher' intern einen StringBuffer verwendet. –

+3

Grundsätzlich habe ich die folgende Methodensignatur: 'public void replaceAll (letzter StringBuilder-Builder, final String regex, letzter String-Ersatz)'. Die Daten des Builders sollten geändert werden, ohne dass eine Neuzuweisung erforderlich ist. –

0

Regex keine wandelbaren CharSequence intern modifizieren. Regex analysiert CharSequence, um eine String zurückzugeben, wobei String das Ergebnis ist. StringBuffer ist eine Ausnahme, da es eine spezielle Behandlung gibt - wie für StringBuilder ist CharSequence, müssen Sie es mit einem Übereinstimmungsergebnis ändern.

Was können Sie stattdessen tun:

// 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!