¿Por qué StringBuilder cuando hay String?

Me encontré con StringBuilder por primera vez y me sorprendió porque Java ya tiene una clase String muy poderosa que permite agregar.

¿Por qué una segunda clase de String ?

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

String no permite agregar. Cada método que invoque en una 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 llamas a 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 , que crearía 500 nuevos objetos de cadena.

Tenga en cuenta que en el ejemplo utilizo un bucle. Como dice helios en los comentarios, el comstackdor traduce automáticamente expresiones como String d = a + b + c a algo así como

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

Tenga en cuenta también que hay StringBuffer además de 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 acceder a él mediante varios hilos, use StringBuffer (que 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 en el rendimiento es significativa.

La clase de cadena 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: Cada vez que hay una necesidad de manipular / actualizar / anexar cadenas muchas veces ve a StringBuilder como eficiente en comparación con String.

StringBuilder es para, bueno, construir cadenas. Específicamente, construirlos de una manera muy eficiente. La clase String es buena para muchas cosas, pero en realidad tiene un rendimiento realmente terrible al ensamblar una nueva cadena de partes de cuerdas más pequeñas porque cada nueva cuerda es una cadena totalmente nueva y reasignada. (Es inmutable ) StringBuilder mantiene la misma secuencia en el 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 cual puede ser una ganancia de rendimiento cuando se modifica una cadena en gran medida. 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 hagas con él, siempre devolverá un nuevo objeto, por ejemplo:

 String s1 = "something"; String s2 = "else"; String s3 = s1 + s2; // this is creating a new object. 

Eficiencia.

Cada vez que concatenas cadenas, se creará una nueva cadena. Por ejemplo:

 String out = "a" + "b" + "c"; 

Esto crea una cadena nueva y temporal, copia “a” y “b” en ella para dar como resultado “ab”. Luego crea otra cadena nueva y temporal, copia “ab” y “c” en ella, para dar como resultado “abc”. Este resultado se asigna a out .

El resultado es un algoritmo de Schlemiel el Pintor de O (n²) (cuadrática) complejidad del tiempo.

StringBuilder , por otro lado, le permite agregar cadenas en el lugar, cambiando el tamaño de la cadena de salida según sea necesario.

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 contrataste a 7 personas diferentes para hacer una búsqueda en Google por ti. 🙂

Para ser precisos, StringBuilder que agrega todas las cadenas es O (N) mientras que la sum de Cadenas 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 longitud de matriz para lograr un rendimiento de O (N ^ 2) ammortizado , 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 al proporcionar una buena estimación inicial en el tamaño final de la cadena.

Java tiene String, StringBuffer y StringBuilder:

  • Cadena: es inmutable

  • StringBuffer: su mutable y ThreadSafe

  • StringBuilder: su mutable pero no ThreadSafe, presentado 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); } } } 
 int wiek = (int)roznica.TotalDays; public double GetRandomNumber(double minimum, double maximum) { Random random = new Random(); return random.NextDouble() * (maximum - minimum) + minimum; } StringBuilder sb = new StringBuilder(); sb.Append(producent + " " + kolor + " " + dataWaznosci.Date + " "); sb.Append(String.Format(" {0:0.00} zł", ObliczCene())); return sb.ToString(); using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace kolos_grD { internal class CenaMinimalnaException:Exception { public CenaMinimalnaException(string exc) : base(exc) { } } } using System.Runtime.Serialization.Formatters.Binary; using System.IO; public void Zapisz(string nazwa) { BinaryFormatter bf = new BinaryFormatter(); FileStream fs = new FileStream(nazwa + ".bin", FileMode.Create); bf.Serialize(fs, this); fs.Close(); } public static Bank Odczytaj(string nazwa) { BinaryFormatter bf = new BinaryFormatter(); FileStream fs = new FileStream(nazwa + ".bin", FileMode.Open); Bank nowy = (Bank) bf.Deserialize(fs); Konto.current_numer_konta = nowy.lista_kont.Last().numer_konta; fs.Close(); return nowy; } public void Sortuj() { List pom = lista_kont.ToList(); pom.Sort(); LinkedList nowa_lista = new LinkedList(pom); lista_kont = nowa_lista; } public int CompareTo(Farba other) { return -this.ObliczCene().CompareTo(other.ObliczCene()); }