2010-11-26 11 views
11

Tengo que escribir algún tipo de analizador sintáctico que obtenga un String y reemplace ciertos conjuntos de caracteres con otros. El código se ve así:La manera más rápida de realizar muchas cadenas reemplazar en Java

noHTMLString = noHTMLString.replaceAll("</p>", "\n"); 
noHTMLString = noHTMLString.replaceAll("<br/>", "\n\n"); 
noHTMLString = noHTMLString.replaceAll("<br />", "\n\n"); 
//here goes A LOT of lines like these ones 

La función es muy larga y realiza una gran cantidad de cadenas reemplaza. El problema aquí es que lleva mucho tiempo porque el método se llama muchas veces, lo que ralentiza el rendimiento de la aplicación.

He leído algunos hilos aquí sobre el uso de StringBuilder como alternativa pero le falta el método ReplaceAll y como se señaló aquí Does string.replaceAll() performance suffer from string immutability? el método replaceAll en clase String trabaja con

Perfil de Compatibilidad & Matcher y Matcher.replaceAll() usa un StringBuilder para almacenar el valor eventualmente devuelto , así que no sé si al cambiar a StringBuilder realmente se reducirá el tiempo para realizar las sustituciones.

¿Conoces una manera rápida de hacer mucho reemplazo de cadenas de forma rápida? ¿Tienes algún consejo para este problema?

Gracias.

EDIT: Tengo que crear un informe que tiene algunos campos con texto html. Para cada fila estoy llamando al método que reemplaza todas las etiquetas html y caracteres especiales dentro de estas cadenas. Con un informe completo, toma más de 3 minutos analizar todo el texto. El problema es que tengo que invocar el método muy a menudo

+0

¿Qué es lo que más te relaja? - La longitud de su texto noHTMLString, o invocar estas tres declaraciones muy a menudo? – Ralph

+0

Tengo que crear un informe que tenga algunos campos con texto html. Para cada fila estoy llamando al método que reemplaza todas las etiquetas html y caracteres especiales dentro de estas cadenas. Con un informe completo, toma más de 3 minutos analizar todo el texto. Entonces, el problema es que tengo que invocar el método muy a menudo. – Averroes

+0

Vea también: http://stackoverflow.com/a/1765616/59087 –

Respuesta

12

Encontré que org.apache.commons.lang.StringUtils es el más rápido si no quieres molestarte con StringBuffer.

Se puede utilizar la siguiente manera:
noHTMLString = StringUtils.replace(noHTMLString, "</p>", "\n");

hice pruebas de rendimiento era fester que mi solución personalizada StrinBuffer similar a la @extraneon propuesto.

+0

Eso fue de hecho más rápido que el replaceAll de String.class. Gracias. – Averroes

+0

Ver [Commons Lang StringUtils.replace performance vs String.replace] (http://stackoverflow.com/questions/16228992/commons-lang-stringutils-replace-performance-vs-string-replace) con referencia. – Vadzim

+0

Para cadenas múltiples, es probablemente más rápido usar [StringUtils.replaceEach] (https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html# replaceEach (java.lang.String,% 20java.lang.String [],% 20java.lang.String [])), no eso [analizando HTML] (http://stackoverflow.com/a/1732454/59087) this el camino es una buena idea –

6

Parece que su HTML de análisis existe, ¿ha pensado en usar un 3rd party library en lugar de reinventar la rueda?

4

Estoy de acuerdo con Martijn en el uso de una solución preparada en lugar de analizarla usted mismo; hay muchas cosas incorporadas en Java en el paquete javax.xml. Una buena solución sería usar la transformación XSLT para reemplazar, esto parece un caso de uso ideal para él. Sin embargo, es complicado.

Para responder a la pregunta, ¿ha considerado usar el regular expression libraries? Parece que tiene muchas cosas diferentes con las que desea coincidir, y las reemplaza con la misma cosa (\ n o cadena vacía). Usando expresiones regulares puede ser una expresión como "<br>|<br/>|<br />" o incluso más inteligente como <br.*?>" para crear un objeto de coincidencia, en el que puede llamar a replaceAll.

+2

No puede analizar HTML con expresiones regulares: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml- etiquetas autocontenidas –

+1

Adriaan, tienes razón, HTML es un lenguaje sin contexto, no es un idioma normal. Pero puedes hacer reemplazos de texto con expresiones regulares, y eso fue lo que se preguntó. – Allanrbo

3

Estoy totalmente de acuerdo con Martijn aquí. Elija la herramienta adecuada para el trabajo.

Si su archivo, sin embargo, no es HTML, pero solo contiene algunos tokens HTML, existen algunas maneras de acelerarlo.

primer lugar, si una cierta cantidad de la entrada no contiene elementos reemplazables, considere comenzar con algo como:

if (!input.contains('<')) { 
    return input; 
} 

segundo lugar, considerar una expresión regular:

Pattern p = Pattern.compile(your_regex); 

No hacer un patrón para cada línea replaceAll, pero intente combinarlas (regex tiene un operador OR) y permita que Pattern optimice la expresión regular. Utilice el patrón compilado y no lo compile en todas las llamadas, es bastante caro.

Si expresiones regulares son un poco más complejo que también se puede aplicar algún motor de reemplazo más rápido (pero potencialmente menos legible) a sí mismo:

StringBuilder result = new StringBuilder(input.length(); 
for (int i=0; i < input.length(); i++) { 
    char c = input.charAt(i); 

    if (c != '<') { 
    continue; 
    } 

    int closePos = input.indexOf('>', i); 
    if (closePos == -1) {// not found 
    result.append(input.substring(i, input.length()); 
    return result.toString(); 
    } 
    i = closePos; 
    String token = input.substring(i, closePos); 
    if (token.equals("p/") { 
    result.append("\\n"); 
    } else if (token.equals(...)) { 
    } else if (...) { 
    } 
} 
return result.toString(); 

Esto puede tener algunos errores :)

La ventaja es que tienes para iterar a través de la entrada solo una vez. La gran desventaja es que no es tan fácil de entender. También podría escribir una máquina de estado, analizando por carácter cuál debería ser el nuevo estado, y eso probablemente sería más rápido e incluso más trabajo.

+1

No se puede analizar HTML con expresiones regulares: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags –

+1

@Adriaan Koster: Eso no es lo que dije. Dije, si tienes HTML usa un analizador HTML. Si se trata de texto sin formato con etiquetas HTML (que no es analizable por un analizador HTML) pruébalo de la manera difícil. – extraneon

+2

@Adriaan: ** INCORRECTO! ** [Sí * puede * analizar HTML con expresiones regulares] (http://stackoverflow.com/questions/4231382/regular-expression-pattern-not-matching-anywhere-in-string/ 4234491 # 4234491). Sin embargo, [probablemente no quieras] (http://stackoverflow.com/questions/4284176/doubt-in-parsing-data-in-perl-where-am-i-going-wrong/4286326#4286326) a menos que tenga HTML restringido y limitado para trabajar, tal como usted mismo ha generado. De lo contrario ** aunque es completamente posible analizar HTML con expresiones regulares **, realmente y realmente no desea hacerlo. – tchrist

Cuestiones relacionadas