Me acabo de encontrar StringBuilder
por primera vez y me sorprendió ya que Java ya tiene una String
clase muy poderosa que permite agregar archivos.
¿Por qué una segunda String
clase?
¿Dónde puedo obtener más información StringBuilder
?
Me acabo de encontrar StringBuilder
por primera vez y me sorprendió ya que Java ya tiene una String
clase muy poderosa que permite agregar archivos.
¿Por qué una segunda String
clase?
¿Dónde puedo obtener más información StringBuilder
?
Respuestas:
String
no permite adjuntar. Cada método que invoca String
crea un nuevo objeto y lo devuelve. Esto se debe a que String
es inmutable, no puede cambiar su estado interno.
Por otro lado StringBuilder
es mutable. Cuando lo llama append(..)
, altera la matriz de caracteres interna, en lugar de crear un nuevo objeto de cadena.
Por lo tanto, es más eficiente tener:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
sb.append(i);
}
en lugar de str += i
, lo que crearía 500 nuevos objetos de cadena.
Tenga en cuenta que en el ejemplo utilizo un bucle. Como Helios señala en los comentarios, el compilador traduce automáticamente expresiones como String d = a + b + c
a algo como
String d = new StringBuilder(a).append(b).append(c).toString();
Tenga en cuenta también que hay StringBuffer
además StringBuilder
. La diferencia es que el primero tiene métodos sincronizados. Si lo usa como una variable local, use StringBuilder
. Si sucede que es posible que varios subprocesos accedan a él, use StringBuffer
(eso es más raro)
Aquí hay un ejemplo concreto de por qué:
int total = 50000;
String s = "";
for (int i = 0; i < total; i++) { s += String.valueOf(i); }
// 4828ms
StringBuilder sb = new StringBuilder();
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); }
// 4ms
Como puede ver, la diferencia de rendimiento es significativa.
s = sb.ToString();
al final para que al menos hayas hecho lo mismo en ambos ejemplos (el resultado es una string
).
La clase String es inmutable mientras que StringBuilder es mutable.
String s = "Hello";
s = s + "World";
El código anterior creará dos objetos porque String es inmutable
StringBuilder sb = new StringBuilder("Hello");
sb.append("World");
El código anterior creará solo un objeto porque StringBuilder no es inmutable.
Lección: Siempre que sea necesario manipular / actualizar / agregar String, muchas veces opte por StringBuilder ya que es eficiente en comparación con String.
StringBuilder es para, bueno, construir cadenas. Específicamente, construyéndolos de una manera muy eficaz. La clase String es buena para muchas cosas, pero en realidad tiene un rendimiento realmente terrible cuando se ensambla una nueva cadena con partes de cadena más pequeñas porque cada nueva cadena es una cadena totalmente nueva y reasignada. (Es inmutable ) StringBuilder mantiene la misma secuencia en su lugar y la modifica ( mutable ).
La clase StringBuilder es mutable y, a diferencia de String, le permite modificar el contenido de la cadena sin necesidad de crear más objetos String, lo que puede ser una ganancia de rendimiento cuando está modificando mucho una cadena. También hay una contraparte para StringBuilder llamada StringBuffer que también está sincronizada, por lo que es ideal para entornos multiproceso.
El mayor problema con String es que cualquier operación que haga con él, siempre devolverá un nuevo objeto, digamos:
String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.
StringBuilder es bueno cuando se trata de cadenas más grandes. Te ayuda a mejorar el rendimiento.
Aquí hay un artículo que encontré que fue útil.
Una búsqueda rápida en Google podría haberte ayudado. Ahora contrató a 7 personas diferentes para hacer una búsqueda en Google por usted. :)
Para ser precisos, StringBuilder al agregar todas las cadenas es O (N) mientras que agregar String es O (N ^ 2). Verificando el código fuente, esto se logra internamente manteniendo una matriz mutable de caracteres. StringBuilder utiliza la técnica de duplicación de la longitud de la matriz para lograr un rendimiento de O (N ^ 2) amortizado , a costa de duplicar potencialmente la memoria requerida. Puede llamar a trimToSize al final para resolver esto, pero generalmente los objetos StringBuilder solo se usan temporalmente. Puede mejorar aún más el rendimiento proporcionando una buena estimación inicial del tamaño final de la cuerda.
Eficiencia.
Cada vez que concatene cadenas, se creará una nueva cadena. Por ejemplo:
String out = "a" + "b" + "c";
Esto crea una nueva cadena temporal, copia "a" y "b" en ella para dar como resultado "ab". Luego crea otra nueva cadena temporal, copia "ab" y "c" en ella, para dar como resultado "abc". A continuación, este resultado se asigna a out
.
El resultado es un algoritmo de Schlemiel the Painter de complejidad temporal O (n²) (cuadrática).
StringBuilder
, por otro lado, le permite agregar cadenas en su lugar, cambiando el tamaño de la cadena de salida según sea necesario.
Java tiene String, StringBuffer y StringBuilder:
Cadena: es inmutable
StringBuffer: es mutable y ThreadSafe
StringBuilder: es mutable pero no ThreadSafe, introducido en Java 1.5
Cadena, por ejemplo:
public class T1 {
public static void main(String[] args){
String s = "Hello";
for (int i=0;i<10;i++) {
s = s+"a";
System.out.println(s);
}
}
}
}
salida: se crearán 10 cadenas diferentes en lugar de solo 1 cadena.
Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa
Helloaaaaaaaaa
Helloaaaaaaaaaa
StringBuilder por ejemplo: solo se creará 1 objeto StringBuilder.
public class T1 {
public static void main(String[] args){
StringBuilder s = new StringBuilder("Hello");
for (int i=0;i<10;i++) {
s.append("a");
System.out.println(s);
}
}
}