numeros - Concatenación de cadenas en Java: cuándo usar+, StringBuilder y concat
stringbuilder java (9)
Desde Java / J2EE Job Interview Companion :
String
String
es inmutable: no puede modificar un objetoString
pero puede reemplazarlo creando una nueva instancia. Crear una nueva instancia es bastante caro.
//Inefficient version using immutable String String output = "Some text"; int count = 100; for (int i = 0; i < count; i++) { output += i; } return output;
El código anterior construiría 99 nuevos objetos
String
, de los cuales 98 se descartarían inmediatamente. Crear nuevos objetos no es eficiente.
StringBuffer
/StringBuilder
StringBuffer
es mutable: useStringBuffer
oStringBuilder
cuando desee modificar los contenidos.StringBuilder
se agregó en Java 5 y es idéntico en todos los aspectos aStringBuffer
excepto que no está sincronizado, lo que lo hace un poco más rápido a costa de no ser seguro para subprocesos.
//More efficient version using mutable StringBuffer StringBuffer output = new StringBuffer(110); output.append("Some text"); for (int i = 0; i < count; i++) { output.append(i); } return output.toString();
El código anterior crea solo dos objetos nuevos,
StringBuffer
y laString
final que se devuelve.StringBuffer
expande según sea necesario, lo cual es costoso, por lo que sería mejor iniciar elStringBuffer
con el tamaño correcto desde el principio, como se muestra.
Esta pregunta ya tiene una respuesta aquí:
¿Cuándo deberíamos usar + para la concatenación de cadenas, cuándo se prefiere StringBuilder y cuándo es adecuado usar concat.
Escuché que StringBuilder es preferible para la concatenación dentro de los bucles. ¿Por que es esto entonces?
Gracias.
El compilador moderno de Java convierte tus operaciones + por el apéndice de StringBuilder. Quiero decir si haces str = str1 + str2 + str3
entonces el compilador generará el siguiente código:
StringBuilder sb = new StringBuilder();
str = sb.append(str1).append(str2).append(str3).toString();
Puede descompilar el código usando DJ o Cavaj para confirmar esto :) Por lo tanto, ahora es más una cuestión de elección que beneficio de rendimiento usar + o StringBuilder :)
Sin embargo, dada la situación en que el compilador no lo hace por usted (si está utilizando un SDK Java privado para hacerlo, entonces puede suceder), entonces seguramente StringBuilder es el camino a seguir ya que termina evitando muchos objetos String
innecesarios.
La ganancia de rendimiento del compilador se aplica a las constantes de concatenación . Los demás usos son en realidad más lentos que usar StringBuilder directamente.
No hay problema con el uso de "+", por ejemplo, para crear un mensaje para Exception porque no ocurre a menudo y la aplicación ya está atornillada en este momento. Evite usar "+" en los bucles.
Para crear mensajes significativos u otras cadenas parametrizadas (expresiones Xpath, por ejemplo) use String.format , es mucho mejor legible.
Mi recomendación sería la siguiente:
-
+
: Úselo al concatenar 2 o 3 cadenas simplemente para mantener su código breve y legible. -
StringBuilder
: se usa cuando se construye una salida de cadena compleja o cuando el rendimiento es una preocupación. -
String.format
: No mencionó esto en su pregunta, pero es mi método preferido para crear Strings, ya que mantiene el código más legible / concisa en mi opinión y es particularmente útil para las declaraciones de registro. -
concat
: No creo que haya tenido motivo para usar esto.
Si todos los elementos concatenados son constantes (ejemplo: "these" + "are" + "constants"
), entonces preferiría el +, porque el compilador alineará la concatenación por usted. De lo contrario, usar StringBuilder es la forma más efectiva.
Si usa + con no constantes, el compilador también usará StringBuilder internamente, pero la depuración se convierte en un infierno, porque el código utilizado ya no es idéntico a su código fuente.
Sugiero usar concat para la concatinación de dos cadenas y StringBuilder, de lo contrario, ver mi explicación para el operador de concatenación (+) vs concat ()
Usa StringBuilder
si haces mucha manipulación. Por lo general, un ciclo es una buena indicación de esto.
La razón de esto es que el uso de concatenación normal produce muchos objetos String
intermedios que no se pueden "extender" fácilmente (es decir, cada operación de concatenación produce una copia , lo que requiere memoria y tiempo de CPU). Por otro lado, un StringBuilder
solo necesita copiar los datos en algunos casos (insertando algo en el medio, o teniendo que cambiar el tamaño porque el resultado es demasiado grande), por lo que guarda esas operaciones de copia.
Usar concat()
no tiene ningún beneficio real sobre el uso de +
(podría ser ligeramente más rápido para un solo +
, pero una vez que haga un a.concat(b).concat(c)
, en realidad será más lento que a + b + c
)
Use + para declaraciones simples y StringBuilder para sentencias / bucles múltiples.
Tiendo a utilizar StringBuilder
en rutas de código donde el rendimiento es una preocupación. La repetida concatenación de cadenas dentro de un bucle suele ser un buen candidato.
La razón para preferir StringBuilder
es que tanto +
como concat
crean un nuevo objeto cada vez que los llamas (siempre que el argumento del lado derecho no esté vacío). Esto puede sumar rápidamente muchos objetos, la mayoría de los cuales son completamente innecesarios.
Como han señalado otros, cuando usa +
varias veces dentro de la misma instrucción, el compilador a menudo puede optimizar esto para usted. Sin embargo, en mi experiencia, este argumento no se aplica cuando las concatenaciones ocurren en declaraciones separadas. Ciertamente no ayuda con los bucles.
Habiendo dicho todo esto, creo que la máxima prioridad debería ser escribir un código claro. Hay algunas excelentes herramientas de creación de perfiles disponibles para Java (uso YourKit), lo que hace que sea muy fácil identificar los cuellos de botella de rendimiento y optimizar solo los bits en los que importa.
PD Nunca he necesitado usar concat
.