¿Cuál es la diferencia entre String y StringBuffer en Java?

¿Cuál es la diferencia entre String y StringBuffer en Java?

¿Hay un tamaño máximo para String?

String se usa para manipular cadenas de caracteres que no se pueden cambiar (solo lectura e inmutables).

StringBuffer se usa para representar caracteres que pueden modificarse.

En cuanto a rendimiento, StringBuffer es más rápido cuando se realizan concatenaciones. Esto se debe a que cuando concatena una String , está creando un nuevo objeto (internamente) cada vez que la String es inmutable.

También puede usar StringBuilder que es similar a StringBuffer excepto que no está sincronizado. El tamaño máximo para cualquiera de estos es Integer.MAX_VALUE (2 31 – 1 = 2,147,483,647) o el tamaño máximo de almacenamiento dynamic dividido por 2 (consulte ¿Cuántos caracteres puede tener Java String? ). Más información aquí .

Una String es inmutable, es decir, cuando se crea, nunca puede cambiar.

Un StringBuffer (o su primo StringBuilder no sincronizado) se usa cuando necesita construir una cuerda pieza por pieza sin la sobrecarga de rendimiento de la construcción de muchas String pequeñas en el camino.

La longitud máxima para ambos es Integer.MAX_VALUE, porque se almacenan internamente como matrices, y las matrices de Java solo tienen un int para su longitud de pseudo-campo.

La mejora del rendimiento entre String y StringBuffer para la concatenación múltiple es bastante significativa. Si ejecuta el siguiente código de prueba, verá la diferencia. En mi computadora portátil antigua con Java 6, obtengo estos resultados:

 Concat con String tomó: 1781ms
 Concat con StringBuffer tomó: 0ms
 public class Concat { public static String concatWithString() { String t = "Cat"; for (int i=0; i<10000; i++) { t = t + "Dog"; } return t; } public static String concatWithStringBuffer() { StringBuffer sb = new StringBuffer("Cat"); for (int i=0; i<10000; i++) { sb.append("Dog"); } return sb.toString(); } public static void main(String[] args) { long start = System.currentTimeMillis(); concatWithString(); System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms"); start = System.currentTimeMillis(); concatWithStringBuffer(); System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms"); } } 
 String StringBuffer Immutable Mutable String s=new String("karthik"); StringBuffer sb=new StringBuffer("karthik") s.concat("reddy"); sb.append("reddy"); System.out.println(s); System.out.println(sb); O/P:karthik O/P:karthikreddy --->once we created a String object ---->once we created a StringBuffer object we can't perform any changes in the existing we can perform any changes in the existing object.If we are trying to perform any object.It is nothing but mutablity of changes with those changes a new object of a StrongBuffer object will be created.It is nothing but Immutability of a String object Use String--->If you require immutabilty Use StringBuffer---->If you require mutable + threadsafety Use StringBuilder--->If you require mutable + with out threadsafety String s=new String("karthik"); --->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object String s="karthik"; --->In this case only one object will be created in scp and s is always pointing to that object only 

String es una clase inmutable. Esto significa que una vez que crea una instancia de una cadena como esta:

 String str1 = "hello"; 

El objeto en la memoria no puede ser alterado. En su lugar, deberá crear una nueva instancia, copiar la cadena anterior y anexar cualquier otra cosa como en este ejemplo:

 String str1 = "hello"; str1 = str1 + " world!"; 

Lo que realmente está sucediendo es que NO estamos actualizando el objeto str1 existente … estamos reasignando memoria nueva todos juntos, copiando los datos “hello” y anexando “mundo!” hasta el final, luego configura la referencia str1 para apuntar a esta nueva memoria. Así que realmente se ve más como esto bajo el capó:

 String str1 = "hello"; String str2 = str1 + " world!"; str1 = str2; 

Por lo tanto, se deduce que este proceso de “copiar y pegar y mover cosas en la memoria” puede ser muy costoso si se realiza de forma repetitiva, especialmente recursiva.

Cuando estás en esa situación de tener que hacer cosas una y otra vez, utilizas StringBuilder. Es mutable y puede agregar cadenas al final de la actual porque está de vuelta por una [matriz en crecimiento] (no 100% si esa es la estructura de datos real, podría ser una lista).

De la API:

Una secuencia de caracteres mutable, segura para hilos. Un buffer de cadena es como una Cadena, pero puede ser modificado. En cualquier momento, contiene una secuencia particular de caracteres, pero la duración y el contenido de la secuencia se pueden cambiar mediante determinadas llamadas a métodos.

Un StringBuffer se usa para crear una única cadena a partir de muchas cadenas, por ejemplo, cuando desea agregar partes de una cadena en un bucle.

Deberías usar un StringBuilder en lugar de un StringBuffer cuando solo tienes un solo subproceso que accede al StringBuffer, ya que el StringBuilder no está sincronizado y, por lo tanto, es más rápido.

AFAIK no existe un límite superior para el tamaño de cadena en Java como lenguaje, pero las JVM probablemente tengan un límite superior.

Encontré respuesta de interés para comparar el rendimiento String vs StringBuffer por Reggie Hutcherso Fuente : http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html

Java proporciona las clases StringBuffer y String, y la clase String se usa para manipular cadenas de caracteres que no pueden modificarse. En pocas palabras, los objetos de tipo String son de solo lectura e inmutables. La clase StringBuffer se usa para representar caracteres que pueden modificarse.

La diferencia de rendimiento significativa entre estas dos clases es que StringBuffer es más rápido que String al realizar concatenaciones simples. En el código de manipulación de cadenas, las cadenas de caracteres se concatenan de forma rutinaria. Con la clase String, las concatenaciones se suelen realizar de la siguiente manera:

  String str = new String ("Stanford "); str += "Lost!!"; 

Si tuviera que usar StringBuffer para realizar la misma concatenación, necesitaría un código que se vea así:

  StringBuffer str = new StringBuffer ("Stanford "); str.append("Lost!!"); 

Los desarrolladores suelen suponer que el primer ejemplo anterior es más eficiente porque piensan que el segundo ejemplo, que utiliza el método de adición para la concatenación, es más costoso que el primer ejemplo, que usa el operador + para concatenar dos objetos de cadena.

El operador + parece inocente, pero el código generado produce algunas sorpresas. Usar un StringBuffer para concatenación puede de hecho 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 bytecode generado de nuestros dos ejemplos. El bytecode para el ejemplo que usa String se ve así:

 0 new #7  3 dup 4 ldc #2  6 invokespecial #12  9 astore_1 10 new #8  13 dup 14 aload_1 15 invokestatic #23  18 invokespecial #13  21 ldc #1  23 invokevirtual #15  26 invokevirtual #22  29 astore_1 

El bytecode 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 bytecode en la ubicación 10 a 29 se ejecuta para la concatenación:

  str += "Lost!!"; 

Las cosas se ponen interesantes aquí. El bytecode generado para la concatenación crea un objeto StringBuffer, luego invoca su método de adición: el objeto temporal StringBuffer se crea en la ubicación 10, y su método de adición se llama en la ubicación 23. Como la clase String es inmutable, se debe usar un StringBuffer para concatenación.

Después de que la concatenación se realiza en el objeto StringBuffer, se debe volver a convertir en una Cadena. Esto se hace con la llamada al método toString en la ubicación 26. Este método crea un nuevo objeto String a partir del objeto temporal StringBuffer. La creación de este objeto temporal StringBuffer y su conversión posterior en un objeto String son muy costosas.

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

  1. Un objeto String en la ubicación 0
  2. Un objeto StringBuffer en la ubicación 10
  3. Un objeto String en la ubicación 26

Ahora, veamos el bytecode generado para el ejemplo usando StringBuffer:

 0 new #8  3 dup 4 ldc #2  6 invokespecial #13  9 astore_1 10 aload_1 11 ldc #1  13 invokevirtual #15  16 pop 

El bytecode en las ubicaciones 0 a 9 se ejecuta para la primera línea de código:

  StringBuffer str = new StringBuffer("Stanford "); 

El bytecode en la ubicación 10 a 16 se ejecuta para la concatenación:

  str.append("Lost!!"); 

Tenga en cuenta que, como es el caso en el primer ejemplo, este código invoca el método de adición de un objeto StringBuffer. A diferencia del primer ejemplo, sin embargo, no es necesario crear un StringBuffer temporal y luego convertirlo en un objeto String. Este código crea solo un objeto, StringBuffer, en la ubicación 0.

En conclusión, la concatenación de StringBuffer es significativamente más rápida que la concatenación de cadenas. Obviamente, StringBuffers debería usarse en este tipo de operación cuando sea posible. Si se desea la funcionalidad de la clase String, considere usar StringBuffer para la concatenación y luego realizar una conversión a String.

Se prefiere un StringBuffer o su hermano más joven y más rápido StringBuilder cada vez que vaya a hacer una gran cantidad de concatenaciones de cadenas en el sabor de

 string += newString; 

o equivalente

 string = string + newString; 

porque las construcciones anteriores implícitamente crean una nueva cadena cada vez que será un gran rendimiento y caída. Un StringBuffer / StringBuilder es mejor para ser comparado con un List dinámicamente expansible.

Una String es una matriz de caracteres inmutables.

Un StringBuffer es una matriz de caracteres mutable. A menudo se convierte de nuevo a String cuando se realiza la mutación.

Como ambos son una matriz, el tamaño máximo para ambos es igual al tamaño máximo de un entero, que es 2 ^ 31-1 (consulte JavaDoc , también consulte JavaDoc para String y StringBuffer ). Esto es porque el .length argumento de una matriz es una primitiva int . (Ver Arrays ).

La cadena es inmutable, lo que significa que cuando realizas una operación en una cadena, realmente estás creando una cadena completamente nueva.

StringBuffer es mutable, y puedes añadirlo a él y restablecer su longitud a 0.

En la práctica, el comstackdor parece usar StringBuffer durante la concatenación de cadenas por motivos de rendimiento .

 String is immutable. 

¿Por qué? Mira aquí .

 StringBuffer is not. It is thread safe. 

Preguntas adicionales como cuándo usar qué y otros conceptos pueden ser resueltos después de esto .

Espero que esto ayude.

Si bien entiendo que este no es un factor importante de diferenciación, me di cuenta hoy de que StringBuffer (y StringBuilder) proporciona algunos métodos interesantes que String no ofrece.

  • marcha atrás()
  • setCharAt ()

Al imprimir el código hash del objeto String / StringBuffer después de probar cualquier operación de adición, el objeto String se vuelve a crear internamente cada vez con nuevos valores en lugar de usar el mismo objeto String.

 public class MutableImmutable { /** * @param args */ public static void main(String[] args) { System.out.println("String is immutable"); String s = "test"; System.out.println(s+"::"+s.hashCode()); for (int i = 0; i < 10; i++) { s += "tre"; System.out.println(s+"::"+s.hashCode()); } System.out.println("String Buffer is mutable"); StringBuffer strBuf = new StringBuffer("test"); System.out.println(strBuf+"::"+strBuf.hashCode()); for (int i = 0; i < 10; i++) { strBuf.append("tre"); System.out.println(strBuf+"::"+strBuf.hashCode()); } } } 

Salida: imprime el valor del objeto junto con su código hash

  String is immutable test::3556498 testtre::-1422435371 testtretre::-1624680014 testtretretre::-855723339 testtretretretre::2071992018 testtretretretretre::-555654763 testtretretretretretre::-706970638 testtretretretretretretre::1157458037 testtretretretretretretretre::1835043090 testtretretretretretretretretre::1425065813 testtretretretretretretretretretre::-1615970766 String Buffer is mutable test::28117098 testtre::28117098 testtretre::28117098 testtretretre::28117098 testtretretretre::28117098 testtretretretretre::28117098 testtretretretretretre::28117098 testtretretretretretretre::28117098 testtretretretretretretretre::28117098 testtretretretretretretretretre::28117098 testtretretretretretretretretretre::28117098 

Las diferencias son

  1. Solo en el operador de la clase String + está sobrecargado. Podemos combinar dos objetos String usando el operador + , pero en el caso de StringBuffer no podemos.
  2. La clase String está anulando aString (), equals (), hashCode () de la clase Object , pero StringBuffer solo anula toString ().

     String s1 = new String("abc"); String s2 = new String("abc"); System.out.println(s1.equals(s2)); // output true StringBuffer sb1 = new StringBuffer("abc"); StringBuffer sb2 = new StringBuffer("abc"); System.out.println(sb1.equals(sb2)); // output false 
  3. La clase String es Serializable y Comparable , pero StringBuffer solo se puede serializar .

     Set set = new TreeSet(); set.add(sb1); set.add(sb2); System.out.println(set); // gives ClassCastException because there is no Comparison mechanism 
  4. Podemos crear un objeto String con y sin un nuevo operador, pero el objeto StringBuffer solo se puede crear con un nuevo operador.

  5. La cadena es inmutable, pero StringBuffer es mutable.
  6. StringBuffer está sincronizado, mientras que String no lo está.
  7. StringBuffer está teniendo un método reverse () incorporado, pero String dosen’t have it.

En cuanto a rendimiento, StringBuffer es mucho mejor que String; porque cada vez que aplica concatenación en String Object, se crean nuevos objetos String en cada concatenación.

Regla principal: la cadena es inmutable (no modificable) y StringBuffer son mutables (modificables)

Aquí está el experimento programático donde obtienes la diferencia de rendimiento

 public class Test { public static int LOOP_ITERATION= 100000; public static void stringTest(){ long startTime = System.currentTimeMillis(); String string = "This"; for(int i=0;i 

La salida de String está en mi máquina 14800

La salida de StringBuffer está en mi máquina 14