JavaRush /Blog Java /Random-ES /Introducción a String, StringBuffer y StringBuilder en Ja...

Introducción a String, StringBuffer y StringBuilder en Java

Publicado en el grupo Random-ES
Hay tres clases en Java para trabajar con datos de texto: String , StringBuffer y StringBuilder . Todo desarrollador se encuentra con el primero al comienzo de aprender el idioma. ¿Qué pasa con los dos restantes? ¿Cuáles son sus diferencias y cuándo es mejor utilizar una u otra clase? En general, la diferencia entre ellos es pequeña, pero es mejor entender todo en la práctica :) Introducción a String, StringBuffer y StringBuilder en Java - 1

clase de cadena

Esta clase representa una secuencia de caracteres. Todos los literales de cadena definidos en programas, como "This is String", son instancias de la clase String. String tiene dos características fundamentales:
  • esta es una clase inmutable
  • esta es la clase final
En general, la clase String no puede tener hijos ( final) y las instancias de la clase no se pueden modificar después de la creación ( immutable). Esto le da a la clase String varias ventajas importantes:
  1. Debido a la inmutabilidad, el código hash de una instancia de la clase String se almacena en caché. No es necesario evaluarlo cada vez porque los valores de los campos del objeto nunca cambiarán después de su creación. Esto proporciona un alto rendimiento al utilizar esta clase como clave para HashMap.

  2. La clase String se puede utilizar en un entorno multiproceso sin sincronización adicional.

  3. Otra característica de la clase String es que sobrecarga el +operador " " en Java. Por tanto, la concatenación (adición) de cadenas es bastante sencilla:

public static void main(String[] args) {
    String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
    System.out.println(command); // Follow the white rabbit
}
En esencia, la concatenación de cadenas se realiza mediante la clase StringBuilder o StringBuffer (a discreción del compilador) y un método append(hablaremos de estas clases un poco más adelante). Si sumamos instancias de la clase String con instancias de otras clases, estas últimas se reducirán a una representación de cadena:
public static void main(String[] args) {
    Boolean b = Boolean.TRUE;
    String result = "b is " + b;
    System.out.println(result); //b is true
}
Esta es otra propiedad interesante de la clase String: los objetos de cualquier clase pueden convertirse en una representación de cadena utilizando el método toString()definido en la clase Objecty heredado por todas las demás clases. A menudo, el método toString() de un objeto se llama implícitamente. Por ejemplo, cuando mostramos algo en pantalla o agregamos un String a un objeto de otra clase. La clase String tiene una característica más. Todos los literales de cadena definidos en código Java, como "asdf", se almacenan en caché en el momento de la compilación y se agregan al llamado grupo de cadenas. Si ejecutamos el siguiente código:
String a = "Wake up, Neo";
String b = "Wake up, Neo";

System.out.println(a == b);
Veremos verdadero en la consola porque las variables aen realidad bse referirán a la misma instancia de la clase String que se agregó al grupo de cadenas en el momento de la compilación. Es decir, no se crean diferentes instancias de la clase con el mismo valor y se ahorra memoria.

Defectos:

No es difícil adivinar que la clase String es necesaria principalmente para trabajar con cadenas. Pero en algunos casos, las características anteriores de la clase String pueden pasar de ser ventajas a desventajas. Una vez que se crean cadenas en código Java, a menudo se realizan muchas operaciones sobre ellas:
  • convertir cadenas a diferentes registros;
  • extracción de subcadenas;
  • concatenación;
  • etc.
Veamos este código:
public static void main(String[] args) {

    String s = " Wake up, Neo! ";
    s = s.toUpperCase();
    s = s.trim();

    System.out.println("\"" + s + "\"");
}
A primera vista, parece que acabamos de traducir la frase "¡Despierta, Neo!" a mayúsculas, eliminó espacios adicionales de esta cadena y la envolvió entre comillas. De hecho, debido a la inmutabilidad de la clase String, como resultado de cada operación se crean nuevas instancias de cadena y las antiguas se descartan, generando una gran cantidad de basura. ¿Cómo evitar el desperdicio de memoria?

Clase StringBuffer

Para manejar la creación de basura temporal debido a modificaciones en un objeto String, puede utilizar la clase StringBuffer. Esta es mutableuna clase, es decir cambiable. Un objeto de la clase StringBuffer puede contener un conjunto específico de caracteres, cuya longitud y valor se pueden cambiar llamando a ciertos métodos. Veamos cómo funciona esta clase. Para crear un nuevo objeto, utilice uno de sus constructores, por ejemplo:
  • StringBuffer() - creará un objeto vacío (sin caracteres)
  • StringBuffer(String str): creará un objeto basado en la variable str (que contiene todos los caracteres de str en la misma secuencia)
Práctica:
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
La concatenación de cadenas a través de StringBuffer en Java se realiza mediante append. En general, el método appendde la clase StringBuffer está sobrecargado de tal manera que puede aceptar casi cualquier tipo de datos:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2));
    sb.append("; ");
    sb.append(false);
    sb.append("; ");
    sb.append(Arrays.asList(1,2,3));
    sb.append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
El método appenddevuelve el objeto sobre el cual fue llamado (como muchos otros métodos), lo que permite llamarlo en una "cadena". El ejemplo anterior se puede escribir así:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2))
            .append("; ")
            .append(false)
            .append("; ")
            .append(Arrays.asList(1,2,3))
            .append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
La clase StringBuffer tiene varios métodos para trabajar con cadenas. Enumeremos los principales:
  • delete(int start, int end)— elimina una subcadena de caracteres comenzando desde la posición starty terminandoend
  • deleteCharAt(int index)— elimina el carácter en la posiciónindex
  • insert(int offset, String str)— inserta una línea stren la posición offset. El método inserttambién está sobrecargado y puede tomar diferentes argumentos.
  • replace(int start, int end, String str)- reemplazará todos los caracteres de una posición starta otra endporstr
  • reverse()— invierte el orden de todos los caracteres
  • substring(int start)- devolverá una subcadena comenzando en la posición start
  • substring(int start, int end)- devolverá una subcadena comenzando de una posición starta otraend
Hay una lista completa de métodos y constructores en la documentación oficial . ¿Cómo funcionan los métodos anteriores? Veamos en la práctica:
public static void main(String[] args) {
     String numbers = "0123456789";

     StringBuffer sb = new StringBuffer(numbers);

     System.out.println(sb.substring(3)); // 3456789
     System.out.println(sb.substring(4, 8)); // 4567
     System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789

     sb = new StringBuffer(numbers);
     System.out.println(sb.reverse()); // 9876543210
     sb.reverse(); // Devolver el pedido original

     sb = new StringBuffer(numbers);
     System.out.println(sb.delete(5, 9)); // 012349
     System.out.println(sb.deleteCharAt(1)); // 02349
     System.out.println(sb.insert(1, "One")); // 0One2349
    }

Ventajas:

  1. Como ya se mencionó, StringBuffer es una clase mutable, por lo que trabajar con él no crea la misma cantidad de basura de memoria que con String. Por lo tanto, si se realizan muchas modificaciones en las cadenas, es mejor utilizar StringBuffer.

  2. StringBuffer es una clase segura para subprocesos. Sus métodos están sincronizados y las instancias pueden ser utilizadas por varios subprocesos simultáneamente.

Defectos:

Por un lado, la seguridad de los hilos es una ventaja de la clase y, por otro lado, es una desventaja. Los métodos sincronizados son más lentos que los métodos no sincronizados. Aquí es donde entra en juego StringBuilder. Averigüemos qué tipo de clase Java es StringBuilder, qué métodos tiene y cuáles son sus características.

Clase StringBuilder

StringBuilder en Java es una clase que representa una secuencia de caracteres. Es muy similar a StringBuffer en todos los aspectos excepto en la seguridad de subprocesos. StringBuilder proporciona una API similar a la de StringBuffer. Demostremos esto usando un ejemplo familiar, reemplazando la declaración de variables de StringBufer a StringBuilder:
public static void main(String[] args) {
    String numbers = "0123456789";

    StringBuilder sb = new StringBuilder(numbers);

    System.out.println(sb.substring(3)); //3456789
    System.out.println(sb.substring(4, 8)); //4567
    System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789

    sb = new StringBuilder(numbers);
    System.out.println(sb.reverse()); //9876543210
    sb.reverse(); // Devolver el pedido original

    sb = new StringBuilder(numbers);
    System.out.println(sb.delete(5, 9)); //012349
    System.out.println(sb.deleteCharAt(1)); //02349
    System.out.println(sb.insert(1, "One")); //0One2349
}
La única diferencia es que StringBuffer es seguro para subprocesos y todos sus métodos están sincronizados, mientras que StringBuilder no. Ésta es la única característica. StringBuilder en Java es más rápido que StringBuffer debido a la falta de sincronización de métodos. Por lo tanto, en la mayoría de los casos, excepto en un entorno multiproceso, es mejor utilizar StringBuilder para un programa Java. Resumimos todo en una tabla comparativa de las tres clases:

Cadena frente a StringBuffer frente a StringBuilder

Cadena búfer de cadena Constructor de cadenas
Posibilidad de cambiar Immutable(No) mutable(Sí) mutable(Sí)
Extensibilidad final(No) final(No) final(No)
Seguridad del hilo Sí, debido a la inmutabilidad. Sí, debido a la sincronización. No
Cuándo usar Cuando se trabaja con cadenas que rara vez se modificarán Cuando se trabaja con cadenas que se modificarán con frecuencia en un entorno de subprocesos múltiples Cuando se trabaja con cadenas que se modificarán con frecuencia en un entorno de un solo subproceso
Puede estudiar este tema con más detalle en el segundo nivel de la misión Java Multithreading en el curso JavaRush:
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION