java metodo Diferencia entre StringBuilder y StringBuffer




stringbuilder java example (24)

¿Cuál es la principal diferencia entre StringBuffer y StringBuilder ? ¿Hay algún problema de rendimiento al decidir sobre alguno de estos?


StringBuilder (introducido en Java 5) es idéntico a StringBuffer , excepto que sus métodos no están sincronizados. Esto significa que tiene mejor rendimiento que este último, pero el inconveniente es que no es seguro para subprocesos.

Lee el tutorial para más detalles.


StringBuffer:

  • Multihilo
  • Sincronizado
  • Lento que StringBuilder

StringBuilder

  • De un solo hilo
  • No sincronizado
  • Más rápido que nunca String

Mejor uso de StringBuilder ya que no está sincronizado y, por lo tanto, tiene un mejor rendimiento. StringBuilder es un reemplazo directo del StringBuffer anterior.



StringBuffer

StringBuffer es mutable significa que uno puede cambiar el valor del objeto. El objeto creado a través de StringBuffer se almacena en el montón. StringBuffer tiene los mismos métodos que StringBuilder, pero cada método en StringBuffer está sincronizado y es StringBuffer seguro para subprocesos.

debido a esto, no permite que dos subprocesos accedan simultáneamente al mismo método. Cada método puede ser accedido por un hilo a la vez.

Pero ser seguro para los subprocesos también tiene desventajas, ya que el rendimiento de StringBuffer se debe a la propiedad segura para los subprocesos. Por lo tanto, StringBuilder es más rápido que el StringBuffer cuando llama a los mismos métodos de cada clase.

Se puede cambiar el valor de StringBuffer, esto significa que se puede asignar al nuevo valor. Hoy en día es una pregunta de entrevista más común, las diferencias entre las clases anteriores. String Buffer se puede convertir a la cadena usando el método toString ().

StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .

demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer

StringBuilder

StringBuilder es el mismo que el StringBuffer, es decir, almacena el objeto en el montón y también se puede modificar. La principal diferencia entre StringBuffer y StringBuilder es que StringBuilder tampoco es seguro para subprocesos. StringBuilder es rápido ya que no es seguro para subprocesos.

StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified

demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder

Recurso: String Vs StringBuffer Vs StringBuilder


Aquí está el resultado de las pruebas de rendimiento para String vs StringBuffer vs StringBuilder . Finalmente, StringBuilder ganó la Prueba. Vea a continuación el código de prueba y el resultado.

Código :

private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test

int loop = 100000;
long start = 0;

// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");

// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");

// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");

  }

Ejecutame en ideone

Resultado :

100000 iteración para agregar un solo texto

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

10000 iteración para agregar un solo texto

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms

StringBuilder es más rápido que StringBuffer porque no está synchronized .

Aquí hay una prueba de referencia simple:

public class Main {
    public static void main(String[] args) {
        int N = 77777777;
        long t;

        {
            StringBuffer sb = new StringBuffer();
            t = System.currentTimeMillis();
            for (int i = N; i --> 0 ;) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }

        {
            StringBuilder sb = new StringBuilder();
            t = System.currentTimeMillis();
            for (int i = N; i > 0 ; i--) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }
    }
}

Una ejecución de prueba da los números de 2241 ms para StringBuffer frente a 753 ms para StringBuilder .


StringBuilder y StringBuffer son casi lo mismo. La diferencia es que StringBuffer está sincronizado y StringBuilder no está sincronizado. Aunque, StringBuilder es más rápido que StringBuffer , la diferencia en el rendimiento es muy pequeña. StringBuilder es un reemplazo de StringBuffer de SUN. Simplemente evita la sincronización de todos los métodos públicos. Más que eso, su funcionalidad es la misma.

Ejemplo de buen uso:

Si su texto va a cambiar y lo utilizan varios subprocesos, entonces es mejor usar StringBuffer . Si su texto va a cambiar pero es usado por un solo hilo, entonces use StringBuilder .


Muy buena pregunta

Aquí están las diferencias, he notado:

StringBuffer: -

StringBuffer is  synchronized
StringBuffer is  thread-safe
StringBuffer is  slow (try to write a sample program and execute it, it will take more time than StringBuilder)

StringBuilder: -

 StringBuilder is not synchronized 
 StringBuilder is not thread-safe
 StringBuilder performance is better than StringBuffer.

Cosa común :-

Ambos tienen los mismos métodos con las mismas firmas. Ambos son mutables.


StringBuffer se utiliza para almacenar cadenas de caracteres que se cambiarán (los objetos de cadena no se pueden cambiar). Se expande automáticamente según sea necesario. Clases relacionadas: String, CharSequence.

StringBuilder se agregó en Java 5. Es idéntico en todos los aspectos a StringBuffer, excepto que no está sincronizado, lo que significa que si varios subprocesos acceden a él al mismo tiempo, podría haber problemas. Para los programas de un solo hilo, el caso más común, al evitar la sobrecarga de sincronización, hace que StringBuilder sea un poco más rápido.


StringBuilder es mucho más rápido que StringBuffer porque no está sincronizado.

Aquí tienes más idea sobre el costo de sincronizar.

Vamos a ver programáticamente cuánto StringBuilder más rápido que StringBuffer

public class Test{  
 public static void main(String[] args){  
    long startTime = System.currentTimeMillis();  
    StringBuffer sb = new StringBuffer("Yasir");  
    for (int i=0; i<10000; i++){  
        sb.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuffer: " + (System.currentTimeMillis() - startTime) + "ms");  
    startTime = System.currentTimeMillis();  
    StringBuilder sb2 = new StringBuilder("Yasir");  
    for (int i=0; i<10000; i++){  
        sb2.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuilder: " + (System.currentTimeMillis() - startTime) + "ms");  
}  
}  

Salida

Tiempo tomado por StringBuffer: 16ms

Tiempo tomado por StringBuilder: 0ms


String es un inmutable.

StringBuffer es un mutable y sincronizado.

StringBuilder también es mutable pero no está sincronizado.


En subprocesos únicos, StringBuffer no es significativamente más lento que StringBuilder , gracias a las optimizaciones de JVM. Y en los subprocesos múltiples, no puedes usar de forma segura un StringBuilder.

Aquí está mi prueba:

public static void main(String[] args) {

    String withString ="";
    long t0 = System.currentTimeMillis();
    for (int i = 0 ; i < 100000; i++){
        withString+="some string";
    }
    System.out.println("strings:" + (System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuffer buf = new StringBuffer();
    for (int i = 0 ; i < 100000; i++){
        buf.append("some string");
    }
    System.out.println("Buffers : "+(System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuilder building = new StringBuilder();
    for (int i = 0 ; i < 100000; i++){
        building.append("some string");
    }
    System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}

Resultados:
cuerdas: 319740
Buffers: 23
Constructor: 7!

Así que los constructores son más rápidos que los buffers, y mucho más rápidos que la concatenación de cadenas. Ahora vamos a usar un Ejecutor para múltiples hilos:

public class StringsPerf {

    public static void main(String[] args) {

        ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        //With Buffer
        StringBuffer buffer = new StringBuffer();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(buffer));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Buffer : "+ AppendableRunnable.time);

        //With Builder
        AppendableRunnable.time = 0;
        executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        StringBuilder builder = new StringBuilder();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(builder));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Builder: "+ AppendableRunnable.time);

    }

   static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // code reduced from Official Javadoc for Executors
        try {
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (Exception e) {}
    }
}

class AppendableRunnable<T extends Appendable> implements Runnable {

    static long time = 0;
    T appendable;
    public AppendableRunnable(T appendable){
        this.appendable = appendable;
    }

    @Override
    public void run(){
        long t0 = System.currentTimeMillis();
        for (int j = 0 ; j < 10000 ; j++){
            try {
                appendable.append("some string");
            } catch (IOException e) {}
        }
        time+=(System.currentTimeMillis() - t0);
    }
}

Ahora los StringBuffers toman 157 ms para 100000 apéndices. No es la misma prueba, pero en comparación con los 37 ms anteriores, puede asumir con seguridad que los apéndices de StringBuffers son más lentos con el uso de subprocesos múltiples . La razón es que el JIT / hotspot / compiler / something realiza optimizaciones cuando detecta que no hay necesidad de verificar bloqueos.

Pero con StringBuilder, tiene java.lang.ArrayIndexOutOfBoundsException , porque un hilo concurrente intenta agregar algo donde no debería.

La conclusión es que no tienes que perseguir a StringBuffers. Y donde tenga hilos, piense en lo que están haciendo, antes de intentar ganar unos nanosegundos.


Constructor de cuerdas :

int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.

Cadena de amortiguación

StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  

Se recomienda utilizar StringBuilder siempre que sea posible porque es más rápido que StringBuffer. Sin embargo, si la seguridad del hilo es necesaria, la mejor opción son los objetos StringBuffer.


El javadoc explica la diferencia:

Esta clase proporciona una API compatible con StringBuffer, pero sin garantía de sincronización. Esta clase está diseñada para usarse como un reemplazo directo de StringBuffer en lugares donde un solo subproceso estaba usando el búfer de cadenas (como suele ser el caso). Donde sea posible, se recomienda que esta clase se use con preferencia a StringBuffer, ya que será más rápida en la mayoría de las implementaciones.


Un programa simple que ilustra la diferencia entre StringBuffer y StringBuilder:

/**
 * Run this program a couple of times. We see that the StringBuilder does not
 * give us reliable results because its methods are not thread-safe as compared
 * to StringBuffer.
 * 
 * For example, the single append in StringBuffer is thread-safe, i.e.
 * only one thread can call append() at any time and would finish writing
 * back to memory one at a time. In contrast, the append() in the StringBuilder 
 * class can be called concurrently by many threads, so the final size of the 
 * StringBuilder is sometimes less than expected.
 * 
 */
public class StringBufferVSStringBuilder {

    public static void main(String[] args) throws InterruptedException {

        int n = 10; 

        //*************************String Builder Test*******************************//
        StringBuilder sb = new StringBuilder();
        StringBuilderTest[] builderThreads = new StringBuilderTest[n];
        for (int i = 0; i < n; i++) {
            builderThreads[i] = new StringBuilderTest(sb);
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].join();
        }
        System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());

        //*************************String Buffer Test*******************************//

        StringBuffer sb2 = new StringBuffer();
        StringBufferTest[] bufferThreads = new StringBufferTest[n];
        for (int i = 0; i < n; i++) {
            bufferThreads[i] = new StringBufferTest(sb2);
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].join();
        }
        System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());

    }

}

// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {

    StringBuilder sb;

    public StringBuilderTest (StringBuilder sb) {
        this.sb = sb;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb.append("A");
        }

    }
}


//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {

    StringBuffer sb2;

    public StringBufferTest (StringBuffer sb2) {
        this.sb2 = sb2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb2.append("A");
        }

    }
}

StringBuilder se introdujo en Java 1.5 por lo que no funcionará con las JVM anteriores.

Desde los StringBuilder :

La clase StringBuilder proporciona una API compatible con StringBuffer, pero sin garantía de sincronización. Esta clase está diseñada para usarse como un reemplazo directo de StringBuffer en lugares donde un solo subproceso estaba usando el búfer de cadenas (como suele ser el caso). Donde sea posible, se recomienda que esta clase se use con preferencia a StringBuffer, ya que será más rápida en la mayoría de las implementaciones.


¿Pero necesitaba obtener la clara diferencia con la ayuda de un ejemplo?

StringBuffer o StringBuilder

Simplemente use StringBuilder menos que realmente esté intentando compartir un búfer entre hilos. StringBuilder es el hermano menor no sincronizado (menos sobrecarga = más eficiente) de la clase StringBuffer sincronizada original.

StringBuffer fue lo primero. Sun estaba preocupado por la corrección en todas las condiciones, por lo que lo sincronizaron para que fuera seguro para subprocesos por si acaso.

StringBuilder llegó más tarde. La mayoría de los usos de StringBuffer eran de un solo hilo y pagaban innecesariamente el costo de la sincronización.

Dado que StringBuilder es un reemplazo StringBuffer para StringBuffer sin la sincronización, no habría diferencias entre los ejemplos.

Si está intentando compartir entre subprocesos, puede usar StringBuffer , pero considere si es necesaria una sincronización de nivel superior, por ejemplo, tal vez en lugar de usar StringBuffer, debería sincronizar los métodos que usan StringBuilder.


La principal diferencia es que StringBuffer está sincronizado pero StringBuilder no. Si necesita usar más de un hilo, entonces se recomienda StringBuilder Pero, según la velocidad de ejecución, StringBuilder es más rápido que StringBuffer , porque no está sincronizado.



Básicamente, los métodos de StringBuffer están sincronizados mientras que StringBuilder no lo está.

Las operaciones son "casi" iguales, pero el uso de métodos sincronizados en un solo hilo es excesivo.

Eso es bastante sobre eso.

Cita de la StringBuilder :

Esta clase [StringBuilder] proporciona una API compatible con StringBuffer, pero sin garantía de sincronización . Esta clase está diseñada para usarse como un reemplazo directo de StringBuffer en lugares donde un solo subproceso estaba usando el búfer de cadenas (como suele ser el caso). Donde sea posible, se recomienda que esta clase se use con preferencia a StringBuffer, ya que será más rápida en la mayoría de las implementaciones.

Así se hizo para sustituirlo.

Lo mismo sucedió con Vector y ArrayList .


Dado que StringBuffer está sincronizado, necesita un esfuerzo adicional, por lo tanto, basado en el rendimiento, es un poco lento que StringBuilder .


StringBuffer es mutable. Puede cambiar en términos de longitud y contenido. Los StringBuffers son seguros para subprocesos, lo que significa que tienen métodos sincronizados para controlar el acceso, de modo que solo un subproceso puede acceder al código sincronizado de un objeto StringBuffer a la vez. Por lo tanto, los objetos StringBuffer son generalmente seguros de usar en un entorno de múltiples subprocesos donde varios subprocesos pueden estar intentando acceder al mismo objeto StringBuffer al mismo tiempo.

StringBuilder La clase StringBuilder es muy similar a StringBuffer, excepto que su acceso no está sincronizado, por lo que no es seguro para subprocesos. Al no estar sincronizado, el rendimiento de StringBuilder puede ser mejor que StringBuffer. Por lo tanto, si está trabajando en un entorno de un solo hilo, el uso de StringBuilder en lugar de StringBuffer puede aumentar el rendimiento. Esto también es válido para otras situaciones, como una variable local de StringBuilder (es decir, una variable dentro de un método) donde solo un hilo accederá a un objeto StringBuilder.


Verifique los elementos internos del método de StringBuffer sincronizada de StringBuffer y el método de StringBuffer no sincronizada de StringBuilder .

StringBuffer :

public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}

public synchronized StringBuffer append(Object obj) {
    super.append(String.valueOf(obj));
    return this;
}

public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}

StringBuilder :

public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

Dado que el apéndice está synchronized , StringBuffer tiene una sobrecarga de rendimiento en comparación con StrinbBuilder en el escenario de subprocesos múltiples. Mientras no esté compartiendo el búfer entre varios subprocesos, use StringBuilder , que es rápido debido a la ausencia de synchronized en los métodos de adición.





stringbuffer