Fehlt mir etwas oder fehlt StringBuilder die gleiche Funktion "Alle Vorkommen eines Strings A durch String B ersetzen" wie die normale String-Klasse? Die StringBuilder-Ersetzungsfunktion ist nicht ganz dieselbe. Gibt es eine Möglichkeit, dies effizienter zu gestalten, ohne mehrere Strings mit der normalen String-Klasse zu generieren?
78
String.replaceAll
die Sache mit Regexs ? Ich würde mir keine Sorgen über den Aufwand beim Konvertieren zwischenStringBuilder
und machenString
.Antworten:
Nun, Sie können eine Schleife schreiben:
public static void replaceAll(StringBuilder builder, String from, String to) { int index = builder.indexOf(from); while (index != -1) { builder.replace(index, index + from.length(), to); index += to.length(); // Move to the end of the replacement index = builder.indexOf(from, index); } }
Beachten Sie, dass die Verwendung in einigen Fällen
lastIndexOf
von hinten schneller sein kann . Ich vermute, dass dies der Fall ist, wenn Sie eine lange Zeichenfolge durch eine kurze ersetzen. Wenn Sie also am Anfang stehen, müssen alle Ersetzungen weniger kopiert werden. Auf jeden Fall sollte dies Ihnen einen Ausgangspunkt geben.quelle
from
undto
unterschiedliche Längen hat diese Lösung Puffer Schwanz auf jedem ersetzen bewegen würde. Dies kann für lange Puffer mit vielen Ersetzungsereignissen ziemlich unwirksam sein. Ron Romeros Antwort hat dieses Manko nicht, sondern beinhaltet eine einzelne Regexp-Suche. Was schneller wäre, hängt wohl vom Anwendungsfall ab.builder = builder.replace(builder.indexOf(from), builder.indexOf(from) + from.length(), to);
Sie können Pattern / Matcher verwenden . Aus den Matcher-Javadocs:
Pattern p = Pattern.compile("cat"); Matcher m = p.matcher("one cat two cats in the yard"); StringBuffer sb = new StringBuffer(); while (m.find()) { m.appendReplacement(sb, "dog"); } m.appendTail(sb); System.out.println(sb.toString());
quelle
$
. Wenn Sie überhaupt nicht auf die übereinstimmende Zeichenfolge verweisen müssen, können Sie den Ersatztext einfach durchlaufenMatcher.quoteReplacement(...)
. Alsom.appendReplacement(sb, Matcher.quoteReplacement(someText));
@Adam: Ich denke, in Ihrem Code-Snippet sollten Sie die Startposition für m.find () verfolgen, da das Ersetzen von Zeichenfolgen den Versatz nach dem letzten übereinstimmenden Zeichen ändern kann.
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) { Matcher m = pattern.matcher(sb); int start = 0; while (m.find(start)) { sb.replace(m.start(), m.end(), replacement); start = m.start() + replacement.length(); } }
quelle
Schauen Sie sich JavaDoc der replaceAll- Methode der String- Klasse an:
Wie Sie sehen können, können Sie dazu Pattern und Matcher verwenden.
quelle
Die Klasse
org.apache.commons.lang3.text.StrBuilder
in Apache Commons Lang ermöglicht das Ersetzen von:public StrBuilder replaceAll(String searchStr, String replaceStr)
* Dies erhält keinen regulären Ausdruck, sondern eine einfache Zeichenfolge.
quelle
Selbst einfach ist es, die String ReplaceAll-Funktion selbst zu verwenden. Sie können es schreiben als
StringBuilder sb = new StringBuilder("Hi there, are you there?") System.out.println(Pattern.compile("there").matcher(sb).replaceAll("niru"));
quelle
Ja. Es ist sehr einfach,
String.replaceAll()
Methode zu verwenden :package com.test; public class Replace { public static void main(String[] args) { String input = "Hello World"; input = input.replaceAll("o", "0"); System.out.println(input); } }
Ausgabe:
Wenn Sie
StringBuilder.replace(int start, int end, String str)
stattdessen wirklich verwenden möchten, können Sie loslegen:public static void main(String args[]) { StringBuilder sb = new StringBuilder("This is a new StringBuilder"); System.out.println("Before: " + sb); String from = "new"; String to = "replaced"; sb = sb.replace(sb.indexOf(from), sb.indexOf(from) + from.length(), to); System.out.println("After: " + sb); }
Ausgabe:
Before: This is a new StringBuilder After: This is a replaced StringBuilder
quelle
java.util.regex.Pattern.matcher (CharSequence s) kann einen StringBuilder als Argument verwenden, sodass Sie jedes Vorkommen Ihres Musters mit start () und end () finden und ersetzen können, ohne builder.toString () aufzurufen.
quelle
Verwenden Sie Folgendes:
/** * Utility method to replace the string from StringBuilder. * @param sb the StringBuilder object. * @param toReplace the String that should be replaced. * @param replacement the String that has to be replaced by. * */ public static void replaceString(StringBuilder sb, String toReplace, String replacement) { int index = -1; while ((index = sb.lastIndexOf(toReplace)) != -1) { sb.replace(index, index + toReplace.length(), replacement); } }
quelle
Hier ist ein vorhandenes replaceAll, das das in StringBuilder übergebene ändert. Ich dachte, ich würde dies posten, da ich ersetzen wollte, ohne einen neuen String zu erstellen.
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) { Matcher m = pattern.matcher(sb); while(m.find()) { sb.replace(m.start(), m.end(), replacement); } }
Ich war schockiert, wie einfach der Code dafür war (aus irgendeinem Grund dachte ich, dass das Ändern des StringBuilder während der Verwendung des Matchers den Start / Ende der Gruppe auslösen würde, aber dies ist nicht der Fall).
Dies ist wahrscheinlich schneller als die anderen Regex-Antworten, da das Muster bereits kompiliert ist und Sie keinen neuen String erstellen, aber kein Benchmarking durchgeführt habe.
quelle
Wie wäre es, eine Methode zu erstellen und
String.replaceAll
sie für Sie erledigen zu lassen:public static void replaceAll(StringBuilder sb, String regex, String replacement) { String aux = sb.toString(); aux = aux.replaceAll(regex, replacement); sb.setLength(0); sb.append(aux); }
quelle
public static String replaceCharsNew(String replaceStr,Map<String,String> replaceStrMap){ StringBuilder replaceStrBuilder = new StringBuilder(replaceStr); Set<String> keys=replaceStrMap.keySet(); for(String invalidChar:keys){ int index = -1; while((index=replaceStrBuilder.indexOf(invalidChar,index)) !=-1){ replaceStrBuilder.replace(index,index+invalidChar.length(),replaceStrMap.get(invalidChar)); } } return replaceStrBuilder.toString(); }
quelle
Ich habe diese Methode gefunden: Matcher.replaceAll (String-Ersetzung); In java.util.regex.Matcher.java sehen Sie mehr:
/** * Replaces every subsequence of the input sequence that matches the * pattern with the given replacement string. * * <p> This method first resets this matcher. It then scans the input * sequence looking for matches of the pattern. Characters that are not * part of any match are appended directly to the result string; each match * is replaced in the result by the replacement string. The replacement * string may contain references to captured subsequences as in the {@link * #appendReplacement appendReplacement} method. * * <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in * the replacement string may cause the results to be different than if it * were being treated as a literal replacement string. Dollar signs may be * treated as references to captured subsequences as described above, and * backslashes are used to escape literal characters in the replacement * string. * * <p> Given the regular expression <tt>a*b</tt>, the input * <tt>"aabfooaabfooabfoob"</tt>, and the replacement string * <tt>"-"</tt>, an invocation of this method on a matcher for that * expression would yield the string <tt>"-foo-foo-foo-"</tt>. * * <p> Invoking this method changes this matcher's state. If the matcher * is to be used in further matching operations then it should first be * reset. </p> * * @param replacement * The replacement string * * @return The string constructed by replacing each matching subsequence * by the replacement string, substituting captured subsequences * as needed */ public String replaceAll(String replacement) { reset(); StringBuffer buffer = new StringBuffer(input.length()); while (find()) { appendReplacement(buffer, replacement); } return appendTail(buffer).toString(); }
quelle