example - ¿Cuál es la diferencia entre String y StringBuffer en Java?
stringbuilder java example (15)
¿Cuál es la diferencia entre String y StringBuffer en Java?
¿Hay un tamaño máximo para String?
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
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.
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<LOOP_ITERATION;i++){
string = string+"Yasir";
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void stringBufferTest(){
long startTime = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer("This");
for(int i=0;i<LOOP_ITERATION;i++){
stringBuffer.append("Yasir");
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void main(String []args){
stringTest()
stringBufferTest();
}
}
La salida de String está en mi máquina 14800
La salida de StringBuffer está en mi máquina 14
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 <Class java.lang.String>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
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:
- Un objeto String en la ubicación 0
- Un objeto StringBuffer en la ubicación 10
- Un objeto String en la ubicación 26
Ahora, veamos el bytecode generado para el ejemplo usando StringBuffer:
0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
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.
La cadena es inmutable, lo que significa que cuando realizas una operación en una cadena, realmente estás creando una cadena completamente nueva.
API: es mutable, y puedes añadirlo a él y restablecer su longitud a 0.
En la práctica, el compilador parece usar StringBuffer durante la concatenación de cadenas por motivos de rendimiento .
Las diferencias son
- 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.
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
La clase String es Serializable y Comparable , pero StringBuffer solo se puede serializar .
Set<StringBuffer> set = new TreeSet<StringBuffer>(); set.add(sb1); set.add(sb2); System.out.println(set); // gives ClassCastException because there is no Comparison mechanism
Podemos crear un objeto String con y sin un nuevo operador, pero el objeto StringBuffer solo se puede crear con un nuevo operador.
- La cadena es inmutable, pero StringBuffer es mutable.
- StringBuffer está sincronizado, mientras que String no lo está.
- StringBuffer está teniendo un método reverse () incorporado, pero String dosen''t have it.
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<Character>
dinámicamente expansible.
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 ()
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).
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.
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 with String took: 1781ms Concat with StringBuffer took: 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");
}
}
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 ).
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 dinámico dividido por 2 (consulte ¿Cuántos caracteres puede tener Java String? ). Más información here .
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