¿Me falta algo, o StringBuilder carece de la misma función "reemplazar todas las apariciones de una cadena A con una cadena B" que la clase String normal? La función de reemplazo de StringBuilder no es exactamente la misma. ¿Hay alguna forma de hacerlo de manera más eficiente sin generar múltiples cadenas utilizando la clase String normal?
79
String.replaceAll
la cosa con las expresiones regulares ? No me preocuparía por la sobrecarga de convertir entreStringBuilder
yString
.Respuestas:
Bueno, puedes escribir un bucle:
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); } }
Tenga en cuenta que en algunos casos puede ser más rápido de usar si se
lastIndexOf
trabaja desde atrás. Sospecho que ese es el caso si está reemplazando una cadena larga por una corta, por lo que cuando llega al principio, cualquier reemplazo tiene menos que copiar. De todos modos, esto debería darte un punto de partida.fuente
from
yto
tengan una longitud diferente, esta solución movería la cola del búfer en cada reemplazo. Esto puede ser bastante ineficaz para un búfer largo con muchas ocurrencias de reemplazo. La respuesta de Ron Romero no tiene esta deficiencia, pero implica una búsqueda de expresiones regulares únicas. Lo que sería más rápido depende del caso de uso, supongo.builder = builder.replace(builder.indexOf(from), builder.indexOf(from) + from.length(), to);
Puede utilizar Pattern / Matcher . Desde los javadocs 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());
fuente
$
. Si no necesita hacer referencia a la cadena coincidente en absoluto, puede ejecutar el texto de reemplazoMatcher.quoteReplacement(...)
. Entoncesm.appendReplacement(sb, Matcher.quoteReplacement(someText));
@Adam: Creo que en su fragmento de código debe rastrear la posición de inicio de m.find () porque el reemplazo de la cadena puede cambiar el desplazamiento después de que el último carácter coincida.
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(); } }
fuente
Mire JavaDoc del método replaceAll de la clase String :
Como puede ver, puede usar Pattern y Matcher para hacer eso.
fuente
La clase
org.apache.commons.lang3.text.StrBuilder
en Apache Commons Lang permite reemplazos:public StrBuilder replaceAll(String searchStr, String replaceStr)
* Esto no recibe una expresión regular sino una cadena simple.
fuente
Incluso uno simple está usando la función String ReplaceAll en sí. Puedes escribirlo como
StringBuilder sb = new StringBuilder("Hi there, are you there?") System.out.println(Pattern.compile("there").matcher(sb).replaceAll("niru"));
fuente
Si. Es un
String.replaceAll()
método muy simple de usar :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); } }
Salida:
Si realmente quieres usar
StringBuilder.replace(int start, int end, String str)
en su lugar, aquí tienes: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); }
Salida:
Before: This is a new StringBuilder After: This is a replaced StringBuilder
fuente
java.util.regex.Pattern.matcher (CharSequence s) puede usar un StringBuilder como argumento para que pueda encontrar y reemplazar cada ocurrencia de su patrón usando start () y end () sin llamar a builder.toString ()
fuente
Utilice lo siguiente:
/** * 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); } }
fuente
Aquí hay un replaceAll en su lugar que modificará el pasado en StringBuilder. Pensé que publicaría esto porque estaba buscando reemplazar todo sin crear una nueva cadena.
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); } }
Me sorprendió lo simple que era el código para hacer esto (por alguna razón pensé que cambiar el StringBuilder mientras usaba el matcher arrojaría el inicio / final del grupo, pero no es así).
Esto es probablemente más rápido que las otras respuestas de expresiones regulares porque el patrón ya está compilado y no está creando una nueva cadena, pero no hice ninguna evaluación comparativa.
fuente
¿Qué tal crear un método y dejar
String.replaceAll
que lo haga por usted?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); }
fuente
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(); }
fuente
Encontré este método: Matcher.replaceAll (reemplazo de cadena); En java.util.regex.Matcher.java puedes ver más:
/** * 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(); }
fuente