example - stringbuilder java 8




Unterschied zwischen StringBuilder und StringBuffer (20)

Aber musste man den deutlichen Unterschied mit Hilfe eines Beispiels herausfinden?

StringBuffer oder StringBuilder

Verwenden Sie StringBuilder einfach, wenn Sie nicht wirklich versuchen, einen Puffer zwischen Threads freizugeben. StringBuilder ist der unsynchronisierte (weniger Overhead = effizientere) jüngere Bruder der ursprünglichen synchronisierten StringBuffer Klasse.

StringBuffer kam zuerst. Sun hat sich unter allen Umständen mit der Korrektheit beschäftigt, also haben sie es synchronisiert, um es für den Fall threadsicher zu machen.

StringBuilder kam später. Die meisten Anwendungen von StringBuffer waren single-thread und zahlten unnötig die Kosten für die Synchronisation.

Da StringBuilder ein Drop-In-Ersatz für StringBuffer ohne die Synchronisation ist, würde es keine Unterschiede zwischen den Beispielen geben.

Wenn Sie versuchen, zwischen Threads zu teilen, können Sie StringBuffer , aber überlegen Sie, ob eine Synchronisierung auf höherer Ebene erforderlich ist, z. B. anstelle von StringBuffer, falls Sie die Methoden synchronisieren, die den StringBuilder verwenden.

Was ist der Hauptunterschied zwischen StringBuffer und StringBuilder ? Gibt es irgendwelche Leistungsprobleme bei der Entscheidung über eine dieser?


Ziemlich gute Frage

Hier sind die Unterschiede, ich habe festgestellt:

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.

Verbreitete Sache :-

Beide haben die gleichen Methoden mit den gleichen Signaturen. Beide sind veränderbar.


Da StringBuffer synchronisiert ist, benötigt es zusätzlichen Aufwand und ist daher auf Grund der Perforamance etwas langsamer als StringBuilder .


Der javadoc erklärt den Unterschied:

Diese Klasse stellt eine API bereit, die mit StringBuffer kompatibel ist, aber keine Synchronisierung garantiert. Diese Klasse wurde als Ersatz für StringBuffer an Stellen entwickelt, an denen der Zeichenfolgenpuffer von einem einzelnen Thread verwendet wurde (wie es normalerweise der Fall ist). Wo es möglich ist, wird empfohlen, diese Klasse vor StringBuffer zu verwenden, da sie unter den meisten Implementierungen schneller ist.



Ein einfaches Programm, das den Unterschied zwischen StringBuffer und StringBuilder veranschaulicht:

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

    }
}

Grundsätzlich sind StringBuffer Methoden synchronisiert, während StringBuilder nicht.

Die Operationen sind "fast" gleich, aber die Verwendung synchronisierter Methoden in einem einzelnen Thread ist übertrieben.

Das ist ziemlich viel darüber.

Zitat aus der StringBuilder :

Diese Klasse [StringBuilder] stellt eine API bereit, die mit StringBuffer kompatibel ist, aber keine Garantie für die Synchronisierung bietet. Diese Klasse wurde als Ersatz für StringBuffer an Stellen entwickelt, an denen der Zeichenfolgenpuffer von einem einzelnen Thread verwendet wurde (wie es normalerweise der Fall ist). Wo es möglich ist, wird empfohlen, diese Klasse vor StringBuffer zu verwenden, da sie unter den meisten Implementierungen schneller ist.

Also wurde es gemacht, um es zu ersetzen.

Das gleiche passiert mit Vector und ArrayList .


In einzelnen Threads ist StringBuffer dank JVM-Optimierungen nicht wesentlich langsamer als StringBuilder . Und beim Multithreading können Sie einen StringBuilder nicht sicher verwenden.

Hier ist mein Test:

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

Ergebnisse :
Zeichenketten: 319740
Puffer: 23
Erbauer: 7!

Builder sind also schneller als Puffer und schneller als String-Verkettung. Jetzt verwenden wir einen Executor für mehrere Threads:

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

Jetzt benötigen StringBuffer 157 ms für 100000 Attends. Es ist nicht der gleiche Test, aber im Vergleich zu den vorherigen 37 ms können Sie sicher davon ausgehen, dass StringBuffers beim Multithreading-Einsatz langsamer ist . Der Grund ist, dass der JIT / Hotspot / Compiler / etwas Optimierungen vornimmt, wenn festgestellt wird, dass keine Sperren überprüft werden müssen.

Aber mit StringBuilder haben Sie java.lang.ArrayIndexOutOfBoundsException , weil ein gleichzeitiger Thread versucht, etwas hinzuzufügen, wo es nicht sollte.

Fazit ist, dass Sie StringBuffers nicht jagen müssen. Und wenn Sie Threads haben, denken Sie darüber nach, was sie tun, bevor Sie versuchen, ein paar Nanosekunden zu gewinnen.


StringBuffer wird verwendet, um Zeichenfolgen zu speichern, die geändert werden (String-Objekte können nicht geändert werden). Es wird automatisch nach Bedarf erweitert. Zugehörige Klassen: String, CharSequence.

StringBuilder wurde in Java 5 hinzugefügt. Es ist in jeder Hinsicht mit StringBuffer identisch, außer dass es nicht synchronisiert ist, was bedeutet, dass, wenn mehrere Threads gleichzeitig auf es zugreifen, es Probleme geben könnte. Bei Single-Thread-Programmen wird der StringBuilder durch den häufigeren Fall, bei dem der Aufwand für die Synchronisierung vermieden wird, geringfügig schneller.


StringBuilder ist nicht threadsicher. String Buffer ist. Mehr Infos here .

EDIT: Was die Leistung betrifft, ist StringBuilder nach dem hotspot der Gewinner. Bei kleinen Iterationen ist der Leistungsunterschied jedoch vernachlässigbar.


StringBuilder wurde in Java 1.5 eingeführt und funktioniert daher nicht mit früheren JVMs.

Von den StringBuilder :

Die StringBuilder-Klasse stellt eine API bereit, die mit StringBuffer kompatibel ist, aber keine Garantie für die Synchronisierung bietet. Diese Klasse wurde als Ersatz für StringBuffer an Stellen entwickelt, an denen der Zeichenfolgenpuffer von einem einzelnen Thread verwendet wurde (wie es normalerweise der Fall ist). Wo es möglich ist, wird empfohlen, diese Klasse vor StringBuffer zu verwenden, da sie unter den meisten Implementierungen schneller ist.


Verwenden Sie StringBuilder besser, da es nicht synchronisiert ist und daher eine bessere Leistung bietet. StringBuilder ist ein Drop-In-Ersatz für den älteren StringBuffer.



StringBuilder ist schneller als StringBuffer da er nicht synchronized .

Hier ist ein einfacher Benchmark-Test:

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

Ein Testlauf ergibt die Anzahl von 2241 ms für StringBuffer vs 753 ms für StringBuilder .


StringBuffer

  • Synchronisiert daher threadsafe
  • fadensicher daher langsam
  • -

StringBuilder

  • Einführung in Java 5.0
  • Asynchron, also schnell und effizient
  • Der Benutzer muss es explizit synchronisieren, wenn er möchte
  • Sie können StringBuilder ohne weitere Änderungen ersetzen

StringBuffer ist synchronisiert, StringBuilder jedoch nicht. Daher ist StringBuilder schneller als StringBuffer .


StringBuilder und StringBuffer sind fast identisch. Der Unterschied besteht darin, dass StringBuffer synchronisiert ist und StringBuilder nicht. Obwohl StringBuilder schneller als StringBuffer , ist der Leistungsunterschied sehr gering. StringBuilder ist ein SUN-Ersatz für StringBuffer . Es vermeidet nur die Synchronisation von allen öffentlichen Methoden. Stattdessen ist ihre Funktionalität die gleiche.

Beispiel für eine gute Nutzung:

Wenn sich Ihr Text ändert und von mehreren Threads verwendet wird, ist es besser, StringBuffer zu verwenden. Wenn sich Ihr Text ändert, aber von einem einzelnen Thread verwendet wird, verwenden Sie StringBuilder .


String-Builder :

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-Puffer

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

Es wird empfohlen, StringBuilder wann immer möglich zu verwenden, da es schneller als StringBuffer ist. Wenn die Thread-Sicherheit jedoch erforderlich ist, ist die beste Option StringBuffer-Objekte.


StringBuffer

StringBuffer ist veränderbar, dh man kann den Wert des Objekts ändern. Das über StringBuffer erstellte Objekt wird im Heap gespeichert. StringBuffer hat dieselben Methoden wie der StringBuilder, aber jede Methode in StringBuffer ist synchronisiert, dh StringBuffer ist threadsicher.

Aus diesem Grund können zwei Threads nicht gleichzeitig auf dieselbe Methode zugreifen. Auf jede Methode kann jeweils nur ein Thread zugreifen.

Aber threadsicher zu sein, hat auch Nachteile, da die Leistung des StringBuffers aufgrund der threadsicheren Eigenschaft beeinträchtigt wird. Daher ist StringBuilder schneller als der StringBuffer, wenn dieselben Methoden für jede Klasse aufgerufen werden.

Der StringBuffer-Wert kann geändert werden, dh er kann dem neuen Wert zugewiesen werden. Heutzutage ist es eine häufigste Interviewfrage, die Unterschiede zwischen den oben genannten Klassen. String Buffer kann mithilfe der toString () -Methode in die Zeichenfolge konvertiert werden.

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 ist identisch mit dem StringBuffer, dh das Objekt wird im Heap gespeichert und kann auch geändert werden. Der Hauptunterschied zwischen dem StringBuffer und dem StringBuilder besteht darin, dass StringBuilder auch nicht Thread-sicher ist. StringBuilder ist schnell, da es nicht threadsicher ist.

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

Ressource: Zeichenfolge Vs StringBuffer Vs StringBuilder


StringBuffer

StringBuffer ist veränderbar, dh man kann den Wert des Objekts ändern. Das über StringBuffer erstellte Objekt wird im Heap gespeichert. StringBuffer hat dieselben Methoden wie der StringBuilder, aber jede Methode in StringBuffer ist synchronisiert, dh StringBuffer ist threadsicher.

StringBuilder

StringBuilder ist identisch mit dem StringBuffer, dh das Objekt wird im Heap gespeichert und kann auch geändert werden. Der Hauptunterschied zwischen StringBuffer und StringBuilder besteht darin, dass StringBuilder nicht Thread-sicher ist. StringBuilder ist schnell, da es nicht threadsicher ist.







stringbuffer