StringBuffer versus String

Java proporciona las clases StringBuffery String, y la Stringclase se utiliza para manipular cadenas de caracteres que no se pueden cambiar. En pocas palabras, los objetos de tipo Stringson de solo lectura e inmutables. La StringBufferclase se utiliza para representar caracteres que se pueden modificar.

La diferencia de rendimiento significativa entre estas dos clases es que StringBufferes más rápido que Stringcuando se realizan concatenaciones simples. En el Stringcódigo de manipulación, las cadenas de caracteres se concatenan de forma rutinaria. Con la Stringclase, las concatenaciones se realizan normalmente de la siguiente manera:

String str = new String ("Stanford"); str + = "¡¡Perdido !!";

Si StringBuffertuviera 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 appendmétodo de concatenación, es más costoso que el primer ejemplo, que usa el +operador para concatenar dos Stringobjetos.

El +operador parece inocente, pero el código generado produce algunas sorpresas. El uso de una StringBufferconcatenació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 Stringve 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 StringBufferobjeto, luego invoca su appendmétodo: el StringBufferobjeto temporal se crea en la ubicación 10 y su appendmétodo se llama en la ubicación 23. Debido a que la Stringclase es inmutable, se StringBufferdebe usar a para la concatenación.

Una vez realizada la concatenación en el StringBufferobjeto, se debe volver a convertir a String. Esto se hace con la llamada al toStringmétodo en la ubicación 26. Este método crea un nuevo Stringobjeto a partir del StringBufferobjeto temporal . La creación de este StringBufferobjeto temporal y su posterior conversión de nuevo en un Stringobjeto son muy costosas.

En resumen, las dos líneas de código anteriores dan como resultado la creación de tres objetos:

  1. Un Stringobjeto en la ubicación 0
  2. Un StringBufferobjeto en la ubicación 10
  3. Un Stringobjeto 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 appendmétodo de un StringBufferobjeto. Sin embargo, a diferencia del primer ejemplo, no es necesario crear un temporal StringBuffery luego convertirlo en un Stringobjeto. Este código crea solo un objeto, el StringBuffer, en la ubicación 0.

En conclusión, la StringBufferconcatenación es significativamente más rápida que la Stringconcatenación. Obviamente, se StringBufferdebe usar s en este tipo de operación cuando sea posible. Si Stringdesea la funcionalidad de la clase, considere usar un StringBufferfor concatenación y luego realizar una conversión a String.

Reggie Hutcherson es un evangelista de la tecnología Sun. Él evangeliza las tecnologías de la plataforma Java 2 de Sun en todo el mundo concentrándose en J2SE y el motor de rendimiento HotSpot.

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.