Java proporciona las clases StringBuffer
y String
, y la String
clase se utiliza para manipular cadenas de caracteres que no se pueden cambiar. En pocas palabras, los objetos de tipo String
son de solo lectura e inmutables. La StringBuffer
clase se utiliza para representar caracteres que se pueden modificar.
La diferencia de rendimiento significativa entre estas dos clases es que StringBuffer
es más rápido que String
cuando se realizan concatenaciones simples. En el String
código de manipulación, las cadenas de caracteres se concatenan de forma rutinaria. Con la String
clase, las concatenaciones se realizan normalmente de la siguiente manera:
String str = new String ("Stanford"); str + = "¡¡Perdido !!";
Si StringBuffer
tuviera que utilizar para realizar la misma concatenación, necesitaría un código que se parece a esto:
StringBuffer str = new StringBuffer ("Stanford"); str.append ("¡¡Perdido !!");
Los desarrolladores generalmente asumen que el primer ejemplo anterior es más eficiente porque piensan que el segundo ejemplo, que usa el append
método de concatenación, es más costoso que el primer ejemplo, que usa el +
operador para concatenar dos String
objetos.
El +
operador parece inocente, pero el código generado produce algunas sorpresas. El uso de una StringBuffer
concatenación for puede producir código que es significativamente más rápido que usar un String
. Para descubrir por qué este es el caso, debemos examinar el código de bytes generado a partir de nuestros dos ejemplos. El código de bytes para el ejemplo usando se String
ve así:
0 nuevo # 7 3 dup 4 ldc # 2 6 invocarespecial # 12 9 astore_1 10 nuevo # 8 13 dup 14 aload_1 15 invokestático # 23 18 invocarespecial # 13 21 ldc # 1 23 invokevirtual # 15 26 invokevirtual # 22 29 astore_1
El código de bytes en las ubicaciones 0 a 9 se ejecuta para la primera línea de código, a saber:
String str = new String ("Stanford");
Luego, el código de bytes en la ubicación 10 a 29 se ejecuta para la concatenación:
str + = "¡¡Perdido !!";
Las cosas se ponen interesantes aquí. El código de bytes generado para la concatenación crea un StringBuffer
objeto, luego invoca su append
método: el StringBuffer
objeto temporal se crea en la ubicación 10 y su append
método se llama en la ubicación 23. Debido a que la String
clase es inmutable, se StringBuffer
debe usar a para la concatenación.
Una vez realizada la concatenación en el StringBuffer
objeto, se debe volver a convertir a String
. Esto se hace con la llamada al toString
método en la ubicación 26. Este método crea un nuevo String
objeto a partir del StringBuffer
objeto temporal . La creación de este StringBuffer
objeto temporal y su posterior conversión de nuevo en un String
objeto son muy costosas.
En resumen, las dos líneas de código anteriores dan como resultado la creación de tres objetos:
- Un
String
objeto en la ubicación 0 - Un
StringBuffer
objeto en la ubicación 10 - Un
String
objeto en la ubicación 26
Ahora, veamos el bytecode generado para el ejemplo usando StringBuffer
:
0 nuevo # 8 3 dup 4 ldc # 2 6 invokeespecial # 13 9 astore_1 10 aload_1 11 ldc # 1 13 invokevirtual # 15 16 pop
El código de bytes en las ubicaciones 0 a 9 se ejecuta para la primera línea de código:
StringBuffer str = new StringBuffer ("Stanford");
A continuación, se ejecuta el código de bytes en la ubicación 10 a 16 para la concatenación:
str.append ("¡¡Perdido !!");
Observe que, como en el caso del primer ejemplo, este código invoca el append
método de un StringBuffer
objeto. Sin embargo, a diferencia del primer ejemplo, no es necesario crear un temporal StringBuffer
y luego convertirlo en un String
objeto. Este código crea solo un objeto, el StringBuffer
, en la ubicación 0.
En conclusión, la StringBuffer
concatenación es significativamente más rápida que la String
concatenación. Obviamente, se StringBuffer
debe usar s en este tipo de operación cuando sea posible. Si String
desea la funcionalidad de la clase, considere usar un StringBuffer
for concatenación y luego realizar una conversión a String
.
Más información sobre este tema
- " JavaWorld presenta una nueva columna semanal de rendimiento de Java", Reggie Hutcherson ( JavaWorld, marzo de 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf.html
- "Los conceptos básicos del rendimiento de Java", Reggie Hutcherson ( JavaWorld, marzo de 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_2.html
- "¿Problema de rendimiento o problema de diseño?" Reggie Hutcherson ( JavaWorld, marzo de 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_3.html
- "Optimizaciones del compilador", Reggie Hutcherson ( JavaWorld, marzo de 2000)
//www.javaworld.com/jw-03-2000/jw-03-javaperf_4.html
Esta historia, "StringBuffer versus String" fue publicada originalmente por JavaWorld.