Sostituisci tutte le occorrenze di una stringa usando StringBuilder?

Mi manca qualcosa o StringBuilder non ha la stessa funzione “sostituisci tutte le occorrenze di una stringa A con stringa B” della normale class String? La funzione di sostituzione di StringBuilder non è esattamente la stessa. C’è un modo per farlo in modo più efficiente senza generare più stringhe usando la normale class String?

Bene, puoi scrivere un ciclo:

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

Nota che in alcuni casi potrebbe essere più veloce usare lastIndexOf , lavorando da dietro. Ho il sospetto che sia il caso se stai sostituendo una stringa lunga con una breve – quindi quando arrivi all’inizio, qualsiasi sostituzione ha meno di una copia. Ad ogni modo, questo dovrebbe darti un punto di partenza.

Potresti usare Pattern / Matcher . Dal javadoc Matcher:

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

Guarda JavaDoc del metodo replaceAll della class String :

Sostituisce ogni sottostringa di questa stringa che corrisponde all’espressione regolare data con la sostituzione fornita. Un’invocazione di questo metodo della forma str.replaceAll (regex, repl) produce esattamente lo stesso risultato dell’espressione

java.util.regex.Pattern.compile (regex) .matcher (str) .ReplaceAll (repl)

Come puoi vedere puoi usare Pattern and Matcher per farlo.

La class org.apache.commons.lang3.text.StrBuilder in Apache Commons Lang consente le sostituzioni:

 public StrBuilder replaceAll(String searchStr, String replaceStr) 

* Questo non riceve un’espressione regolare ma una semplice stringa.

@Adam: Penso che nel tuo frammento di codice dovresti tracciare la posizione iniziale per m.find () perché la sostituzione della stringa può cambiare l’offset dopo che l’ultimo carattere è stato abbinato.

 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(); } } 

Anche uno semplice usa la funzione String ReplaceAll stessa. Puoi scriverlo come

 StringBuilder sb = new StringBuilder("Hi there, are you there?") System.out.println(Pattern.compile("there").matcher(sb).replaceAll("niru")); 

java.util.regex.Pattern.matcher (CharSequence s) può utilizzare un object StringBuilder come argomento in modo da poter trovare e sostituire ogni occorrenza del modello usando start () e end () senza chiamare builder.toString ()

Utilizza il seguente:

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

Ecco un sostituto in posto che modificherà il passato in StringBuilder. Ho pensato che avrei postato questo come stavo cercando di fare replaceAll senza creare una nuova stringa.

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

Sono rimasto scioccato dal fatto che il codice per farlo fosse semplice (per qualche motivo pensavo che cambiare StringBuilder mentre si utilizzava il matcher avrebbe gettato il gruppo all’inizio / fine ma non lo ha fatto).

Questo è probabilmente più veloce delle altre risposte regex perché il pattern è già compilato e non si sta creando una nuova String ma non ho fatto alcun benchmarking.

Che ne dici di creare un metodo e lasciare che String.replaceAll faccia per te:

 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); } 
 public static String replaceCharsNew(String replaceStr,Map replaceStrMap){ StringBuilder replaceStrBuilder = new StringBuilder(replaceStr); Set 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(); } 

Ho trovato questo metodo: Matcher.replaceAll (sostituzione di stringhe); In java.util.regex.Matcher.java puoi vedere di più:

  /** * Replaces every subsequence of the input sequence that matches the * pattern with the given replacement string. * * 

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. * *

Note that backslashes (\) and dollar signs ($) 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. * *

Given the regular expression a*b, the input * "aabfooaabfooabfoob", and the replacement string * "-", an invocation of this method on a matcher for that * expression would yield the string "-foo-foo-foo-". * *

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.

* * @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(); }

Sì. È molto semplice utilizzare il metodo String.replaceAll() :

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

Produzione:

 Hell0 W0rld