2011-10-19 20 views
29

Cuándo deberíamos usar + para la concatenación de cadenas, cuándo se prefiere StringBuilder y cuándo es adecuado usar concat.Concatenación de cadenas en Java: cuándo usar +, StringBuilder y concat

He oído que StringBuilder es preferible para la concatenación dentro de los bucles. ¿Por que es esto entonces?

Gracias.

+0

primera cosa que viene a la mente es que todos y cada vez que utilice una cadena sencilla, se puede asignar un objeto (proporcionar trabajo a GarbageCollector), mientras usa un StringBuilder o un StringBuffer lo mantiene trabajando con un solo objeto. – BigMike

Respuesta

20

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 + y concat crear un nuevo objeto cada vez que usted los llama (siempre que el argumento 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 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.

P.S. Nunca he necesitado usar concat.

+0

Solo una vez he usado 'concat()', y eso fue para reemplazar 'str ->" foo "+ str' con una referencia de método:' "foo" :: concat'. – shmosel

40

El compilador de Java moderno convierte tus operaciones + por el apéndice de StringBuilder. Quiero decir si lo hace 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(); 

Usted puede descompilar código usando DJ o Cavaj confirmar esto :) Así que ahora es más una cuestión de elección de beneficio en el rendimiento de use + o StringBuilder :)

Sin embargo, dado 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, como usted terminan evitando muchos objetos innecesarios String.

+8

Sí, pero si usa '+' en un bucle, el tiempo de ejecución creará un nuevo 'StringBuilder' para cada iteración que conlleva una gran penalización de rendimiento. –

+1

puede tener STringBuilder creado antes del inicio del ciclo. Si crea StringBuilder cada vez en bucle, perderá todos los datos previos de StringBuilder. – Saurabh

+0

@Sahil: el compilador u optimizador puede arreglar eso. –

5

Si todos los elementos concatenados son constantes (ejemplo: "these" + "are" + "constants"), entonces preferiría el signo +, 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.

2

Mi recomendación sería la siguiente:

  • +: se utiliza cuando la concatenación de 2 o 3 cadenas simplemente para mantener su breve código y legible.
  • StringBuilder: Úselo 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 cadenas 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.
1

Use StringBuilder si hace mucha manipulación. Generalmente un bucle es una buena indicación de esto.

La razón de esto es que el uso de concatenación normal produce un montón de intermedio String objeto que no puede ser fácilmente "extendida" (es decir, cada operación de concatenación produce una copia, lo que requiere la memoria y la CPU tiempo para hacer). Un StringBuilder, por otro lado, 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.

Usando concat() no tiene ninguna ventaja real sobre el uso de + (que podría ser ligeramente más rápido para un solo +, pero una vez que a.concat(b).concat(c) en realidad será más lento que a + b + c).

1

La ganancia de rendimiento del compilador se aplica a las constantes concatenadas . El resto de los usos son en realidad más lentos que usar StringBuilder directamente.

No hay problema con el uso de "+", p. para crear un mensaje para Exception porque no sucede a menudo y la aplicación ya de alguna manera está jodida en este momento. Evite utilizar "+" en los bucles.

Para crear mensajes significativos u otras cadenas parametrizados (por ejemplo, las expresiones XPath) utilizan String.Format - es mucho mejor legible.

1

Use + para declaraciones simples y StringBuilder para varias instrucciones/bucles.

11

De Java/J2EE Job Interview Companion:

String

String es inmutable: no se puede modificar un objeto String pero puede reemplazarlo mediante la creación de 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 podría construir 99 nuevos String objetos, de los cuales 98 serían arrojados de inmediato. Crear nuevos objetos no es eficiente.

StringBuffer/StringBuilder

StringBuffer es mutable: utilizar StringBuffer o StringBuilder cuando se quiere modificar el contenido.StringBuilder se agregó en Java 5 y es idéntico en todos los aspectos a StringBuffer, 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 dos nuevos objetos, la StringBuffer y la final String que se devuelve. StringBuffer se expande según sea necesario, lo cual es costoso, por lo que sería mejor inicializar el StringBuffer con el tamaño correcto desde el principio, como se muestra.

+0

más 1 para el enlace del libro. (No se puede agregar el signo '+' como "Los comentarios no pueden contener ese contenido" :)) –

Cuestiones relacionadas