¿Por qué StringBuilder cuando hay String?

82

Me acabo de encontrar StringBuilderpor primera vez y me sorprendió ya que Java ya tiene una Stringclase muy poderosa que permite agregar archivos.

¿Por qué una segunda Stringclase?

¿Dónde puedo obtener más información StringBuilder?

an00b
fuente
Solo quería señalar que esto surgió como una pregunta de entrevista para mí una vez. Me preguntaron qué haría para rellenar una cadena grande ...
paso

Respuestas:

171

Stringno permite adjuntar. Cada método que invoca Stringcrea un nuevo objeto y lo devuelve. Esto se debe a que Stringes inmutable, no puede cambiar su estado interno.

Por otro lado StringBuilderes 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 + ca algo como

String d = new StringBuilder(a).append(b).append(c).toString();

Tenga en cuenta también que hay StringBufferademá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)

Bozho
fuente
24
+1. Podría agregar: "por lo tanto, StrungBuilder busca rendimiento" y "Los compiladores de Java sustituyen expresiones como A + B + C con el nuevo StringBuilder (A) .append (B) .append (C) .toString () para evitar el rendimiento de creación de objetos sanciones ":)
helios
y todo muchas gracias. Todos merecen +1 (que se entregarán de inmediato :)
an00b
super como el recuerdo de objetos "inmutables".
Gary Tsui
Grandes respuestas. Sin embargo, lo que echo de menos es la razón por la que no podemos hacer que el compilador averigüe cuándo usar Stringbuilder la mayor parte del tiempo , incluidos los bucles for, para que no tenga que pensar en ello como un desarrollador. :)
worldsayshi
Buena respuesta . Me gustaría agregar estas líneas: String es inmutable ya que la matriz (es decir, el valor char []) que contiene la cadena se declara final, pero en el caso de StringBuilder, la matriz (es decir, el valor char []) que contiene la cadena no es final. Puede realizar cambios en la matriz que contiene la cadena en el caso de Stringbuilder
Deen John
60

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.

Amir Raminfar
fuente
PD. Ejecuté esto en mi Macbook Pro Dual core.
Amir Raminfar
Esto no explica por qué
Steve Kuo
25
Esto explica ¿Por qué StringBuilder cuando hay String? Esto no explica por qué StringBuilder es tan rápido. Pero esa no es la pregunta. Entonces esta es una respuesta válida.
Kerem Baydoğan
2
@krmby - De acuerdo. Responder por qué en realidad es para otra pregunta.
Amir Raminfar
12
Creo que para que la comparación sea justa, debes incluir el tiempo para realizar una s = sb.ToString();al final para que al menos hayas hecho lo mismo en ambos ejemplos (el resultado es una string).
Scott Whitlock
19

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.

unk1102
fuente
8

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 ).

Rex M
fuente
5

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.
CarlosZ
fuente
4

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. :)

Vanchinathan Chandrasekaran
fuente
¿No estamos todos haciendo trabajos no remunerados aquí?
Deadpool
4

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.

caoba
fuente
3

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.

Thomas
fuente
Muchas implementaciones de JVM compilarán su ejemplo en un StringBuilder y luego convertirán el resultado final en String. En tal caso, no se ensamblará mediante asignaciones de cadenas repetidas.
scottb
1

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);
        }
    }
}
Kumar Vivek Mitra
fuente