String vs. StringBuffer vs. StringBuilder PDF Imprimir Correo electrónico
Escrito por Leonardo De Seta   
Miércoles 03 de Diciembre de 2008 11:00

tijerasLa concatenación de cadena de caracteres, representada por la clase String en Java, es una tarea muy habitual en prácticamente cualquier programa. Sea para construir un mensaje, errores, excepciones o log de la aplicación, la concatenación de String está siempre presente.

En Java hay varias formas de concatenar los String, y su rendimiento difiere muchísimo. Vamos a ver las tres formas más habituales de concatenar String: la "clásica" con el operador de suma, usando StringBuffer y usando StringBuilder.

Los contendientes

El operador suma

El operador de suma está sobrecargado para los String, y es la forma más básica de concatenar dos cadenas de caracteres. Y también, es la peor forma en cuanto a rendimiento.

Al concatener dos String con el operador suma, se crea un nuevo String resultante, con lo que constantemente estamos creando objetos nuevos.

La concatenación con el operador de suma se ve algo así:

String hola = "Hola, ";
String mundo = "mundo";

String holamundo = hola + mundo;

La clase StringBuffer

StringBuffer es una secuencia de caracteres mutable; es decir, es una clase que nos permite concatenar String de una manera simple y muy eficiente.

Los métodos de StringBuffer son sincronizados, por lo cual la podemos usar de manera segura en un ambiente de multihilos.

StringBuffer se usa de la siguiente manera:

StringBuffer holamundoBuffer = new StringBuffer();
holamundoBuffer.append("Hola, ");
holamundoBuffer.append("mundo");

String holamundo = holamundoBuffer.toString();

La clase StringBuilder

StringBuilder es una clase que aparece con el JDK 5, y es la clase recomendada para la concatenación de String en la mayoría de los casos. Su uso es idéntico al StringBuffer (tienen el mismo API), por lo resulta relativamente simple reemplazar a los StringBuffer por StringBuilder.

Los métodos de StringBuilder no son sincronizados, por lo que tiene mejor rendimiento que StringBuffer. En general, la concatenación de String ocurre con variables locales a un método, por lo que es seguro usar StringBuilder en lugar de StringBuffer. En métodos que hacen uso intensivo de la concatenación, la diferente en rendimiento puede ser importante.

StringBuilder se usa de la siguiente manera:

StringBuilder holamundoBuilder = new StringBuilder();
holamundoBuilder.append("Hola, ");
holamundoBuilder.append("mundo");

String holamundo = holamundoBuilder.toString();

Midiendo el rendimiento de StringBuffer y StringBuilder

Pero, ¿qué tan más rápido es un StringBuilder? A modo de ejemplo, vamos a concatener un millón de String ("zim") a un StringBuilder y a un StringBuffer, y compararemos los tiempos. El código que ejecutaremos será el siguiente:

        StringBuffer sbuffer = new StringBuffer();
inicio = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
sbuffer.append("zim");
}
fin = System.currentTimeMillis();
System.out.println("Tiempo del StringBuffer: " + (fin-inicio));

StringBuilder sbuilder = new StringBuilder();
inicio = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
sbuilder.append("zim");
}
fin = System.currentTimeMillis();
System.out.println("Tiempo del StringBuilder: " + (fin-inicio));

Con varias ejecuciones, los tiempos son constantemente menores para el StringBuilder:

  • StringBuffer: 93 milisegundos en concatenar un millón de String
  • StringBuilder: 47 milisegundos en concatenar un millón de String

Es decir, en la mayoría de los casos, StringBuilder puede resultar un 50% más rápido para concatenar String.

¿Y el operador de suma?

La misma prueba con el operador de suma se lleva una eternidad, ya que la creación constante de nuevos objetos hace que la JVM tenga que empezar a limpiar continuamente el Heap. A modo de referencia, concatener tan sólo 100.000 String con el operador de suma se demora 99812 milisegundos, por lo que su rendimiento no tiene comparación.

Conclusión

En la amplia mayoría de los casos es recomendable utilizar la clase StringBuilder para concatenar cadenas de caracteres. La clase StringBuilder tiene el mismo API que StringBuffer, por lo que reemplazar código que usa StringBuffer es relativamente sencillo.

La única salvedad sería si la concatenación ocurre en un entorno multihilos, donde diferentes hilos van modificando la misma concatenación. De todas formas, en la mayoría de los casos la concatenación ocurre en variables locales dentro de métodos, por lo que el uso de StringBuilder sigue siendo la opción recomendada.

Comentarios
Añadir nuevo Buscar
+/-
Escribir comentario
Nombre:
Email:
 
Título:
Código UBB:
[b] [i] [u] [url] [quote] [code] [img] 
 
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch::(:shock:
:X:side::):P:unsure::woohoo::huh::whistle:;):s:!::?::idea::arrow:
 
Uva   |Author |2008-12-03 08:32:56
interesante nota!
Luís Carlos Moreira da Costa  - !StringBuilder && !StringBuffer   |201.13.49.xxx |2008-12-03 12:10:27
Existe uma maneira mais rápida do que o StringBuilder e também StringBuffer.

Luis Carlos Moreira
Eclipse RAP, RCP, GEF Platform Developer
Pentaho Bussiness Platform Developer
victor  - re: !StringBuilder && !StringBuffer   |213.139.21.xxx |2008-12-03 23:57:36
Luís Carlos Moreira da Costa escribió:
Existe uma maneira mais rápida do que o StringBuilder e também StringBuffer.

Luis Carlos Moreira
Eclipse RAP, RCP, GEF Platform Developer
Pentaho Bussiness Platform Developer


No sei si e unha afirmacion o unha pregunta, pero en caso de que se sexa unha afirmacion pon isa maneira.


PD - > interesante articluo
Antuan  - Felicidades   |195.55.46.xxx |2008-12-04 00:57:44
Gran Análisis
federico  - muy bueno   |190.2.53.xxx |2008-12-04 03:23:40
muy bueno el articulo.

Aunque a veces me hace pensar... por agregar nuevos objetos como StringBuffer y StringBuilder, y no arreglar de una vez la falta de rendimiento del operador suma.

Saludos!
cbalvarez   |Author |2008-12-04 09:06:52
En Java 1.6 está, al menos parcialmente, solucionado (o java 6, que se yo, ya me perdí con el sistema de notación).

Se puede ver así: compilé lo siguiente con java 1.6

String s = "aaa" + "BBBBBB";
s = "ASASA" + "FDFD";
s = s + "AAAAAAA";

Descompilado es esto:

String s = "aaaBBBBBB";
s = "ASASAFDFD";
s = (new StringBuilder()).append(s).append("AAAAAAA" .toString();


Esto no soluciona del todo el problema porque si la última linea estuviera en un bucle, estás creando un objeto StringBuilder por cada ciclo, lo que es definitivamente menos performante que hacer un stringBuffer.append(s), pero sí te evita tener que hacer un StringBuffer si estás en los casos de arriba, o tenés un println o algo así.
cbalvarez   |Author |2008-12-04 09:07:51
El smile es porque me olvidé de encodear ) .
Kasu   |201.148.36.xxx |2008-12-04 15:46:13
Y si se corre el ejemplo al reves... me da estos tiempos:

Tiempo del StringBuilder: 94
Tiempo del StringBuffer: 93

y al reves quiero decir haciendo primero el clico del String Builder y despues el del String Buffer.



StringBuilder sbuilder = new StringBuilder();
inicio = System.currentTimeMillis();
for (int i=0; i
cbalvarez   |Author |2008-12-05 03:47:23
Yo diría que una diferencia de 50 milisegundos entre dos corridas de un millón de operaciones es estadisticamente insignificante, particularmente si hubo una sola corrida.

La diferencia puede tener que ver con el trabajo del garbage collector, con la CPU libre en la máquina en esos momentos (si se hizo en una PC con windows, bueno, windows es impredecible y andá a saber que estaba haciendo justo cuando se corrió cada test)
javier  - Mmmm   |189.183.2.xxx |2008-12-06 16:01:46
Buen articulo yo ya sabia esto, y lo uso adecuadamente pero nunca habia hecho benchmarks.

Y aprovechando el codigo de aqui lo corri y mi sirpresa fue que en todos los casos StringBuffer fue mas rapido que StringBuilder. Probe diferentes cantidades de iteraciones, diferentes javas(1.5 sun,ibm. 1.6 sun) siempre StringBuffer mas rapido. Aprox 20% mas rapido.

Por q sera?

Teoricamente StringBuilder es mas rapido
javier  - Update   |189.183.2.xxx |2008-12-06 16:08:14
Lo anterior pasa si lo corro desde nb 6.5 con java 6.

En la consola StringBuilder es siempre menor
leito   |Publisher |2008-12-07 03:30:48
avatar Raro, porque las pruebas que hice para armar el artículo también fueron sobre NetBeans 6.5 con Java 6.
Vacuela  - Nenaxo   |63.95.59.xxx |2008-12-08 09:51:43
Buen Articulo

Saludos

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 

Últimos comentarios