Diferencia entre StringBuilder y StringBuffer


1578

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

Respuestas:


1667

StringBufferestá sincronizado, StringBuilderno lo está.


239
y StringBuilder pretende ser una gota en el reemplazo para StringBuffer donde no se requiere la sincronización
Joel

95
y la sincronización prácticamente nunca es necesaria. Si alguien quiere sincronizar en un StringBuilder, puede rodear todo el bloque de código con un (sb) {} sincronizado en la instancia
locka

23
@locka Diría que StringBuffer nunca es una buena idea (a menos que tenga una API que lo requiera) vanillajava.blogspot.de/2013/04/…
Peter Lawrey

8
El único lugar que veo para un StringBuffer es una consola como salida y varias utilidades de registro: muchos subprocesos pueden salir en conflicto. Como no desea que se mezclen 2 salidas ... pero generalmente la sincronización en el nivel de StringBuffer es demasiado baja, deseará sincronizar en un apéndice como levelm, por lo que bloquear una respuesta es lo mejor y StringBuffer debe ser desaprobado. Ahorraría tiempo de revisión de código con los novatos.
Remi Morin

20
Buena mnemotécnica para quienes mezclan estos dos: BuFFer era Primero, más antiguo y, por lo tanto, una implementación sincronizada. La nueva clase de generador utiliza el patrón de generador y es asíncrona.
Datageek

728

StringBuilderes más rápido que StringBufferporque no lo es 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 prueba de funcionamiento da los números de 2241 msfor StringBuffervs 753 msfor StringBuilder.


10
Cambié el literal de la cadena a algo más grande: "el zorro marrón rápido" y obtuve resultados más interesantes. Básicamente, son casi tan rápidos. De hecho, me quedé sin memoria, así que tuve que quitar algunos sietes. Explicación: la sincronización está optimizada por el punto de acceso. Básicamente, solo está midiendo el tiempo que toma el punto de acceso para hacer esto (y probablemente algunas optimizaciones más).
Jilles van Gurp

77
Necesitas calentar antes. Esta prueba es injusta para StringBuffer. Además, sería bueno si realmente añadiera algo. En realidad, volteé la prueba, agregué una secuencia aleatoria y obtuve la prueba opuesta. Se dice que no se puede confiar en puntos de referencia simples. Lo contrario muestra que StringBuffer es más rápido. 5164 para StringBuilder vs 3699 para StringBuffer hastebin.com/piwicifami.avrasm
mmm

75
Esta es la primera vez que veo --> 0en un bucle. Me tomó un momento darme cuenta de lo que significa. ¿Es esto algo que realmente se usa en la práctica en lugar de la ...; i > 0; i--sintaxis habitual ?
Raimund Krämer

19
Eso i -->es realmente molesto en cuanto a la sintaxis ... Al principio pensé que era una flecha debido a los comentarios sobre el arte ASCII.
Sameer Puri

14
Otros concluyen con diferentes resultados: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html . Los puntos de referencia realmente deberían hacerse con JMH, no con un simple main()Además, su punto de referencia es injusto. No hay calentamiento.
Lukas Eder

249

Básicamente, los StringBuffermétodos se sincronizan mientras que StringBuilderno.

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

Eso es más o menos al respecto.

Cita de la API 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 para StringBuffer en lugares donde un único subproceso estaba utilizando el búfer de cadena (como suele ser el caso). Siempre que 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.

Entonces se hizo para sustituirlo.

Lo mismo sucedió con Vectory ArrayList.


1
También con Hashtabley HashMap.
shmosel

177

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

StringBuffer o StringBuilder

Simplemente use a StringBuildermenos que realmente esté tratando de compartir un búfer entre hilos. StringBuilderes el hermano menor no sincronizado (menos sobrecarga = más eficiente) de la StringBufferclase sincronizada original .

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

StringBuildervino después La mayoría de los usos de StringBuffereran de un solo hilo y pagaban innecesariamente el costo de la sincronización.

Dado que StringBuilderes un reemplazo directo StringBuffersin la sincronización, no habría diferencias entre los ejemplos.

Si está tratando de compartir entre hilos, puede usar StringBuffer, pero considere si es necesaria una sincronización de nivel superior, por ejemplo, tal vez en lugar de usar StringBuffer, si sincroniza los métodos que usan StringBuilder.


14
La primera buena respuesta! El punto es "a menos que esté compartiendo un búfer entre hilos"
AlexWien

1
respuesta muy detallada!
Raúl

81

Primero veamos las similitudes : StringBuilder y StringBuffer son mutables. Eso significa que puede cambiar el contenido de ellos, en la misma ubicación.

Diferencias : StringBuffer también es mutable y está sincronizado. Donde como StringBuilder es mutable pero no está sincronizado de forma predeterminada.

Significado de sincronizado (sincronización) : cuando algo está sincronizado, pueden acceder múltiples hilos y modificarlo sin ningún problema o efecto secundario. StringBuffer está sincronizado, por lo que puede usarlo con múltiples hilos sin ningún problema.

¿Cuál usar cuando? StringBuilder: cuando necesita una cadena, que puede ser modificable, y solo un hilo está accediendo y modificándola. StringBuffer: cuando necesita una cadena, que puede ser modificable, y múltiples hilos están accediendo y modificándola.

Nota : No use StringBuffer innecesariamente, es decir, no lo use si solo un subproceso está modificando y accediendo a él porque tiene mucho código de bloqueo y desbloqueo para la sincronización que innecesariamente tomará tiempo de CPU. No use cerraduras a menos que sea necesario.


2
Solo quiero mencionar que las llamadas al método INDIVIDUAL de StringBuffer son seguras para subprocesos. Pero si tiene varias líneas de código, use un bloque de código sincronizado para garantizar la seguridad del subproceso, con algo de bloqueo / monitor (como de costumbre ...). Básicamente, ¡no asuma que usar una biblioteca segura para subprocesos garantiza inmediatamente la seguridad de subprocesos en SU ​​programa!
Kevin Lee

57

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

Aquí está mi prueba (no un punto de referencia, solo una 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:
cadenas: 319740
Buffers: 23
Generador: 7!

Por lo tanto, los constructores son más rápidos que los búferes, y MUCHO más rápido que la concatenación de cadenas. Ahora usemos 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 tardan 157 ms para 100000 anexos. No es la misma prueba, pero en comparación con los 37 ms anteriores, puede asumir con seguridad que los anexos de StringBuffers son más lentos con el uso de subprocesos múltiples . La razón es que el JIT / punto de acceso / compilador / algo hace optimizaciones cuando detecta que no hay necesidad de verificar los 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 pocos nanosegundos.


55
Has olvidado hacer "t0 = System.currentTimeMillis ();" antes de hacer la prueba StringBuilder. Entonces, la figura que se muestra para StringBuilder es en realidad el tiempo que tardó en ejecutar la prueba de stringbuffer AND stringbuilder. Agregue esta línea y verá que StringBuilder ES más rápido DOS VECES.
Gena Batsyan

Tenga en cuenta que withString+="some string"+i+" ; ";no es equivalente a los otros dos bucles y, por lo tanto, no es una comparación justa.
Dave Jarvis

Exacto, corregido. Las cadenas de pensamiento siguen siendo muy lentas.
Nicolas Zozol

¿Puede explicar más por qué el aumento de ArrayIndexOutOfBoundsException para StringBuilder
Alireza Fattahi

Debe usar JMH para los puntos de referencia. Su punto de referencia es realmente inexacto.
Lukas Eder

42

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

De los Javadocs :

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 para StringBuffer en lugares donde un único subproceso estaba utilizando el búfer de cadena (como suele ser el caso). Siempre que 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.


13
1.4 está al final de su vida útil, por lo que no parece que valga la pena preocuparse por la versión anterior a la 1.5.
Tom Hawtin - tackline

@ tomHawtin-tackline no necesariamente: hay productos empresariales disponibles en pre 1.4 que la mayoría de nosotros usamos a diario. Además, BlackBerry java se basa en 1.4 y eso todavía es muy actual.
Richard Le Mesurier

Y CDC y CLDC no tienen StringBuilder.
Jin Kwon

37

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


23

StringBuffer

  • Sincronizado, por lo tanto, seguro
  • Hilo seguro por lo tanto lento

StringBuilder

  • Introducido en Java 5.0
  • Asíncrono, por lo tanto, rápido y eficiente
  • El usuario necesita explícitamente sincronizarlo, si quiere
  • Puede reemplazarlo StringBuffersin ningún otro cambio

NOTA: Solo las operaciones individuales son seguras para subprocesos, las operaciones múltiples no lo son. por ejemplo, si se llama appenddos veces, o appendy toStringno no es seguro.
Peter Lawrey

22

StringBuilder no es seguro para subprocesos. String Buffer es. Más información aquí .

EDITAR: En cuanto al rendimiento, después de que se activa el punto de acceso , StringBuilder es el ganador. Sin embargo, para pequeñas iteraciones, la diferencia de rendimiento es insignificante.


21

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

Ejemplo de buen uso:

Si su texto va a cambiar y es usado por múltiples hilos, entonces es mejor usarlo StringBuffer. Si su texto va a cambiar pero es usado por un solo hilo, entonces úselo StringBuilder.


19

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, es decir, StringBuffer es seguro para subprocesos.

Debido a esto, no permite que dos hilos accedan simultáneamente al mismo método. Se puede acceder a cada método por un hilo a la vez.

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

El valor de StringBuffer se puede cambiar, 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 mediante 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 igual que 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

ingrese la descripción de la imagen aquí

Recurso: String Vs StringBuffer Vs StringBuilder


StringBuilder es inmutable y el tipo de cadena es mutable
Brinda Rathod

No estaría de acuerdo en que Strings y StringBuilders son "rápidos" y que StringBuffers son "muy lentos". Ver las respuestas anteriores.
FireCubez

17

String Es un inmutable.

StringBuffer Es un mutable y sincronizado.

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


Además, StringBuffer bloquea los subprocesos para acceder a estos datos seguros de subprocesos, por eso la operación va lentamente. StringBuilder no bloquea el hilo y se ejecuta en modo Multi Threading, por eso es rápido. String: cuando no necesita concatenar string, esta es una buena manera, pero cuando lo necesita, use StringBuilder -> porque String crea cada vez un nuevo objeto en el montón, pero StringBuilder devuelve el mismo objeto ...
Musa

11

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 para StringBuffer en lugares donde un único subproceso estaba utilizando el búfer de cadena (como suele ser el caso). Siempre que 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.


10

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

Lea el tutorial para más detalles.


6

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");
        }

    }
}

4

StringBuffer se usa 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 al mismo tiempo, podría haber problemas. Para los programas de un solo subproceso, el caso más común, evitar la sobrecarga de sincronización hace que StringBuilder sea un poco más rápido.


44
Los programas de subproceso único no son el caso más común en Java, pero los StringBuilder‍s generalmente son locales para un método, donde solo son visibles para un subproceso.
finnw

4

StringBufferestá sincronizado, pero StringBuilderno lo está. Como resultado, StringBuilderes más rápido que StringBuffer.


4

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 subprocesos múltiples 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 subproceso único, el uso de StringBuilder en lugar de StringBuffer puede aumentar el rendimiento. Esto también es cierto para otras situaciones, como una variable local StringBuilder (es decir, una variable dentro de un método) donde solo un hilo accederá a un objeto StringBuilder.


4

StringBuffer:

  • Multihilo
  • Sincronizado
  • Lento que StringBuilder

StringBuilder

  • Single-Thread
  • No sincronizado
  • Cadena más rápida que nunca

2
Más precisamente, String c = a + bes equivalente a String c = new StringBuilder().append(a).append(b).toString(), por lo que no es más rápido. Es sólo que crear uno nuevo para cada asignación de cadena, mientras que usted podría tener sólo uno ( String d = a + b; d = d + c;es String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();mientras StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();se ahorraría una instanciation StringBuilder).
Chop

4

Constructor de cadenas :

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.

String-Buffer

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

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


Si necesita seguridad de subprocesos, la mejor opción es usar StringBuilder ya que StringBuffer solo es seguro para subprocesos para operaciones individuales. Para múltiples operaciones, necesita un bloqueo explícito.
Peter Lawrey el

4

Mejor uso StringBuilderya que no está sincronizado y, por lo tanto, ofrece un mejor rendimiento. StringBuilderes un reemplazo directo de los más antiguos StringBuffer.


3
@Mark true pero la mayoría de las veces StringBu(ff|ild)eres una variable local utilizada solo por un solo hilo.
gabuzo

1
@MarkMcKenna: Incluso en una aplicación de subprocesos múltiples, a menudo uno tendría que usar un bloqueo externo o hacer un trabajo adicional para evitarlo. Por ejemplo, si dos subprocesos desean agregar un registro que contiene múltiples cadenas a un generador de cadenas, tendrían que agregar los datos que se agregarán y luego agregarlos como una unidad, incluso si hubiera sido más rápido, sin problemas de subprocesos. simplemente realizar una secuencia de operaciones de anexos discretos.
supercat

3

Dado que StringBufferestá sincronizado, necesita un esfuerzo adicional, por lo tanto, basado en perforación, es un poco más lento que StringBuilder.


3

No hay diferencias básicas entre StringBuildery StringBuffer, solo existen unas pocas diferencias entre ellos. En StringBufferlos métodos están sincronizados. Esto significa que a la vez solo un hilo puede operar en ellos. Si hay más de un hilo, el segundo tendrá que esperar a que termine el primero y el tercero tendrá que esperar a que terminen el primero y el segundo, y así sucesivamente. Esto hace que el proceso sea muy lento y, por lo tanto, el rendimiento en el caso StringBufferes bajo.

Por otro lado, StringBuilderno está sincronizado. Esto significa que a la vez pueden operar múltiples hilos en el mismo StringBuilderobjeto al mismo tiempo. Esto hace que el proceso sea muy rápido y, por lo tanto, el rendimiento StringBuilderes alto.


3

A Stringes un objeto inmutable, lo que significa que el valor no se puede cambiar mientras que StringBufferes mutable.

El StringBufferestá sincronizado, por lo tanto Hilo de seguridad mientras que StringBuilderno y adecuado es, por únicos casos de un único subproceso.


3
el hecho de que StringBuffer tenga código sincronizado no significa necesariamente que StringBuffer sea seguro para subprocesos. Considere el siguiente ejemplo: StringBuffer testingBuffer = "stackoverflow"; Ahora Thread-1 está tratando de agregar "1" a testingBuffer, y Thread-2 está tratando de agregar "2" a testingBuffer. Ahora, aunque el método append () esté sincronizado, no puede estar seguro de si el valor de testingBuffer será "stackoverflow12" o "stackoverflow21". En realidad, Oracle le recomienda usar stringbuilder sobre stringbuffer. Espero que esto haya ayudado :)
Biman Tripathy

2

La principal diferencia es que StringBufferestá sincronizada, pero no lo StringBuilderestá. Si necesita usar más de un hilo, se recomienda StringBuffer. Pero , según la velocidad de ejecución, StringBuilderes más rápida que StringBufferporque no está sincronizada.


44
StringBuffer solo es seguro para subprocesos si realiza solo una operación en él. No recomendaría usarlo en múltiples hilos porque es muy difícil hacerlo bien.
Peter Lawrey

@PeterLawrey, ¿qué quieres decir? :-)
Tamad Lang

1
@ b16db0 Quiero decir que la mayoría de los usos de StringBuffer no son seguros para subprocesos, ya que realizan múltiples llamadas sin sincronización externa, lo que hace que la clase sea bastante inútil.
Peter Lawrey

@ PeterLawrey ah, es como si StringBuffer todavía necesita un entorno sincronizado.
Tamad Lang

2

Verifique las partes internas del método de adición sincronizada de StringBuffery el método de adición 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;
}

Como agregar es synchronized, StringBuffertiene una sobrecarga de rendimiento en comparación con el StrinbBuilderescenario de subprocesos múltiples. Siempre y cuando no esté compartiendo el búfer entre varios subprocesos, use StringBuilder, lo que es rápido debido a la ausencia de synchronizedmétodos in append.


1

Aquí está el resultado de la prueba 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 iteraciones para agregar un solo texto

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

10000 iteraciones para agregar un solo texto

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

1
  • StringBuffer es seguro para subprocesos, pero StringBuilder no es seguro para subprocesos.
  • StringBuilder es más rápido que StringBuffer.
  • StringBuffer está sincronizado, mientras que StringBuilder no está sincronizado.

1

StringBuffer está sincronizado y es seguro para subprocesos, StringBuilder no está sincronizado y es más rápido.


Esta diferencia se ha dado en todas las otras respuestas a esta pregunta. ¿Podrías destacar algo nuevo?
Nico Haase
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.