it-swarm.com.de

StringBuilder vs String-Verkettung in toString () in Java

In Anbetracht der folgenden 2 toString() -Implementierungen wird diese bevorzugt:

public String toString(){
    return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}

oder

public String toString(){
    StringBuilder sb = new StringBuilder(100);
    return sb.append("{a:").append(a)
          .append(", b:").append(b)
          .append(", c:").append(c)
          .append("}")
          .toString();
}

?

Was noch wichtiger ist, da wir nur 3 Eigenschaften haben, macht es vielleicht keinen Unterschied, aber zu welchem ​​Zeitpunkt würden Sie von + concat zu StringBuilder wechseln?

868
non sequitor

Version 1 ist vorzuziehen, weil sie kürzer ist und der Compiler wird sie tatsächlich in Version 2 umwandeln - überhaupt kein Leistungsunterschied.

Noch wichtiger ist, dass wir nur drei Eigenschaften haben, es macht vielleicht keinen Unterschied, aber zu welchem ​​Zeitpunkt wechseln Sie von Concat zu Builder?

An dem Punkt, an dem Sie in einer Schleife verketten, kann der Compiler in der Regel StringBuilder nicht selbst ersetzen.

911

Der Schlüssel ist, ob Sie eine einzelne Verkettung an einem Ort schreiben oder sie im Laufe der Zeit anhäufen.

Für das angegebene Beispiel hat es keinen Sinn, StringBuilder explizit zu verwenden. (Sehen Sie sich den kompilierten Code für Ihren ersten Fall an.)

Wenn Sie jedoch eine Zeichenfolge erstellen, z. Verwenden Sie in einer Schleife StringBuilder.

Nehmen wir an, dass hugeArray Tausende von Zeichenfolgen enthält, um dies zu verdeutlichen:

...
String result = "";
for (String s : hugeArray) {
    result = result + s;
}

ist sehr zeit- und speicherverschwenderisch im Vergleich zu:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();
233
joel.neely

Ich bevorzuge:

String.format( "{a: %s, b: %s, c: %s}", a, b, c );

... weil es kurz und lesbar ist.

Ich würde dies nicht für die Geschwindigkeit optimieren , es sei denn, Sie verwenden es in einer Schleife mit einer sehr hohen Wiederholungszahl und haben den Leistungsunterschied gemessen.

Ich stimme zu, dass, wenn Sie viele Parameter ausgeben müssen, dieses Formular verwirrend werden kann (wie einer der Kommentare sagt). In diesem Fall würde ich zu einer besser lesbaren Form wechseln (vielleicht mit ToStringBuilder von Apache-commons - aus der Antwort von matt b) und die Leistung wieder ignorieren.

71
tangens

In den meisten Fällen sehen Sie keinen Unterschied zwischen den beiden Ansätzen, aber es ist einfach, ein Worst-Case-Szenario wie das folgende zu erstellen:

public class Main
{
    public static void main(String[] args)
    {
        long now = System.currentTimeMillis();
        slow();
        System.out.println("slow elapsed " + (System.currentTimeMillis() - now) + " ms");

        now = System.currentTimeMillis();
        fast();
        System.out.println("fast elapsed " + (System.currentTimeMillis() - now) + " ms");
    }

    private static void fast()
    {
        StringBuilder s = new StringBuilder();
        for(int i=0;i<100000;i++)
            s.append("*");      
    }

    private static void slow()
    {
        String s = "";
        for(int i=0;i<100000;i++)
            s+="*";
    }
}

Die Ausgabe ist:

slow elapsed 11741 ms
fast elapsed 7 ms

Das Problem ist, dass durch das Anhängen von + = an eine Zeichenfolge eine neue Zeichenfolge rekonstruiert wird. Dies kostet etwas Lineares in Bezug auf die Länge Ihrer Zeichenfolgen (Summe aus beiden).

Also - zu deiner Frage:

Der zweite Ansatz wäre schneller, aber weniger lesbar und schwerer zu pflegen. Wie gesagt, in Ihrem speziellen Fall würden Sie den Unterschied wahrscheinlich nicht sehen.

70
Omry Yadan

Ich hatte auch einen Konflikt mit meinem Chef über die Tatsache, ob ich Append oder + verwenden soll. Wie sie Append verwenden (ich kann immer noch nicht herausfinden, wie sie jedes Mal sagen, wenn ein neues Objekt erstellt wird). Also habe ich mir überlegt, ein bisschen F & E zu machen, obwohl ich die Erklärung von Michael Borgwardt liebe, aber ich wollte nur eine Erklärung zeigen, ob jemand es in Zukunft wirklich wissen muss.

/**
 *
 * @author Perilbrain
 */
public class Appc {
    public Appc() {
        String x = "no name";
        x += "I have Added a name" + "We May need few more names" + Appc.this;
        x.concat(x);
        // x+=x.toString(); --It creates new StringBuilder object before concatenation so avoid if possible
        //System.out.println(x);
    }

    public void Sb() {
        StringBuilder sbb = new StringBuilder("no name");
        sbb.append("I have Added a name");
        sbb.append("We May need few more names");
        sbb.append(Appc.this);
        sbb.append(sbb.toString());
        // System.out.println(sbb.toString());
    }
}

und Demontage der oben genannten Klasse kommt als

 .method public <init>()V //public Appc()
  .limit stack 2
  .limit locals 2
met001_begin:                                  ; DATA XREF: met001_slot000i
  .line 12
    aload_0 ; met001_slot000
    invokespecial Java/lang/Object.<init>()V
  .line 13
    ldc "no name"
    astore_1 ; met001_slot001
  .line 14

met001_7:                                      ; DATA XREF: met001_slot001i
    new Java/lang/StringBuilder //1st object of SB
    dup
    invokespecial Java/lang/StringBuilder.<init>()V
    aload_1 ; met001_slot001
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    ldc "I have Added a nameWe May need few more names"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    aload_0 ; met001_slot000
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    invokevirtual Java/lang/StringBuilder.toString()Ljava/lang/String;
    astore_1 ; met001_slot001
  .line 15
    aload_1 ; met001_slot001
    aload_1 ; met001_slot001
    invokevirtual Java/lang/String.concat(Ljava/lang/String;)Ljava/lang/Strin\
g;
    pop
  .line 18
    return //no more SB created
met001_end:                                    ; DATA XREF: met001_slot000i ...

; ===========================================================================

;met001_slot000                                ; DATA XREF: <init>r ...
    .var 0 is this LAppc; from met001_begin to met001_end
;met001_slot001                                ; DATA XREF: <init>+6w ...
    .var 1 is x Ljava/lang/String; from met001_7 to met001_end
  .end method
;44-1=44
; ---------------------------------------------------------------------------


; Segment type: Pure code
  .method public Sb()V //public void Sb
  .limit stack 3
  .limit locals 2
met002_begin:                                  ; DATA XREF: met002_slot000i
  .line 21
    new Java/lang/StringBuilder
    dup
    ldc "no name"
    invokespecial Java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    astore_1 ; met002_slot001
  .line 22

met002_10:                                     ; DATA XREF: met002_slot001i
    aload_1 ; met002_slot001
    ldc "I have Added a name"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 23
    aload_1 ; met002_slot001
    ldc "We May need few more names"
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 24
    aload_1 ; met002_slot001
    aload_0 ; met002_slot000
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/Object;)Ljava/lan\
g/StringBuilder;
    pop
  .line 25
    aload_1 ; met002_slot001
    aload_1 ; met002_slot001
    invokevirtual Java/lang/StringBuilder.toString()Ljava/lang/String;
    invokevirtual Java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lan\
g/StringBuilder;
    pop
  .line 28
    return
met002_end:                                    ; DATA XREF: met002_slot000i ...


;met002_slot000                                ; DATA XREF: Sb+25r
    .var 0 is this LAppc; from met002_begin to met002_end
;met002_slot001                                ; DATA XREF: Sb+9w ...
    .var 1 is sbb Ljava/lang/StringBuilder; from met002_10 to met002_end
  .end method
;96-49=48
; ---------------------------------------------------------------------------

Anhand der beiden obigen Codes können Sie sehen, dass Michael Recht hat. Es wird jeweils nur ein SB-Objekt erstellt.

27
perilbrain

Seit Java 1.5 generiert eine einfache einzeilige Verkettung mit "+" und StringBuilder.append () genau den gleichen Bytecode.

Verwenden Sie daher zur besseren Lesbarkeit des Codes "+".

2 Ausnahmen:

  • multithread-Umgebung: StringBuffer
  • verkettung in Schleifen: StringBuilder/StringBuffer
24
Zofren

Unter Verwendung der neuesten Version von Java (1.8) zeigt die Disassembly (javap -c) die vom Compiler eingeführte Optimierung. + sowie sb.append() erzeugen einen sehr ähnlichen Code. Es lohnt sich jedoch, das Verhalten zu untersuchen, wenn wir + in einer for-Schleife verwenden.

Hinzufügen von Zeichenfolgen mit + in einer for-Schleife

Java:

public String myCatPlus(String[] vals) {
    String result = "";
    for (String val : vals) {
        result = result + val;
    }
    return result;
}

ByteCode: (for Schleifenauszug)

12: iload         5
14: iload         4
16: if_icmpge     51
19: aload_3
20: iload         5
22: aaload
23: astore        6
25: new           #3                  // class Java/lang/StringBuilder
28: dup
29: invokespecial #4                  // Method Java/lang/StringBuilder."<init>":()V
32: aload_2
33: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: aload         6
38: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: invokevirtual #6                  // Method Java/lang/StringBuilder.toString:()Ljava/lang/String;
44: astore_2
45: iinc          5, 1
48: goto          12

Hinzufügen von Strings mit stringbuilder.append

Java:

public String myCatSb(String[] vals) {
    StringBuilder sb = new StringBuilder();
    for(String val : vals) {
        sb.append(val);
    }
    return sb.toString();
}

ByteCdoe: (for Schleifenauszug)

17: iload         5
19: iload         4
21: if_icmpge     43
24: aload_3
25: iload         5
27: aaload
28: astore        6
30: aload_2
31: aload         6
33: invokevirtual #5                  // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
36: pop
37: iinc          5, 1
40: goto          17
43: aload_2

Es gibt ein bisschen eklatanter Unterschied. In dem ersten Fall, in dem + verwendet wurde, wird für jede Schleifeniteration ein neues StringBuilder erstellt, und das erzeugte Ergebnis wird durch Ausführen eines toString() -Aufrufs (29 bis 41) gespeichert. Sie generieren also Zwischen-Strings, die Sie wirklich nicht benötigen, wenn Sie den Operator + in der for -Schleife verwenden.

22
ring bearer

In Java 9 sollte die Version 1 schneller sein, da sie in den Aufruf invokedynamic konvertiert wird. Weitere Details finden Sie in JEP-28 :

Die Idee ist, den gesamten StringBuilder-Append-Tanz durch einen einfachen aufgerufenen dynamischen Aufruf von Java.lang.invoke.StringConcatFactory zu ersetzen, der die Werte akzeptiert, die verkettet werden müssen.

10
ZhekaKozlov

Aus Leistungsgründen wird von der Verwendung von += (String Verkettung) abgeraten. Der Grund dafür ist: Java String ist unveränderlich, jedes Mal, wenn eine neue Verkettung durchgeführt wird, wird ein neuer String erstellt (der neue hat bereits einen anderen Fingerabdruck als der ältere) im String-Pool ). Durch das Erstellen neuer Zeichenfolgen wird der GC unter Druck gesetzt und das Programm verlangsamt: Die Erstellung von Objekten ist teuer.

Der folgende Code sollte es gleichzeitig praktischer und klarer machen.

public static void main(String[] args) 
{
    // warming up
    for(int i = 0; i < 100; i++)
        RandomStringUtils.randomAlphanumeric(1024);
    final StringBuilder appender = new StringBuilder();
    for(int i = 0; i < 100; i++)
        appender.append(RandomStringUtils.randomAlphanumeric(i));

    // testing
    for(int i = 1; i <= 10000; i*=10)
        test(i);
}

public static void test(final int howMany) 
{
    List<String> samples = new ArrayList<>(howMany);
    for(int i = 0; i < howMany; i++)
        samples.add(RandomStringUtils.randomAlphabetic(128));

    final StringBuilder builder = new StringBuilder();
    long start = System.nanoTime();
    for(String sample: samples)
        builder.append(sample);
    builder.toString();
    long elapsed = System.nanoTime() - start;
    System.out.printf("builder - %d - elapsed: %dus\n", howMany, elapsed / 1000);

    String accumulator = "";
    start = System.nanoTime();
    for(String sample: samples)
        accumulator += sample;
    elapsed = System.nanoTime() - start;
    System.out.printf("concatenation - %d - elapsed: %dus\n", howMany, elapsed / (int) 1e3);

    start = System.nanoTime();
    String newOne = null;
    for(String sample: samples)
        newOne = new String(sample);
    elapsed = System.nanoTime() - start;
    System.out.printf("creation - %d - elapsed: %dus\n\n", howMany, elapsed / 1000);
}

Die Ergebnisse für einen Lauf sind unten angegeben.

builder - 1 - elapsed: 132us
concatenation - 1 - elapsed: 4us
creation - 1 - elapsed: 5us

builder - 10 - elapsed: 9us
concatenation - 10 - elapsed: 26us
creation - 10 - elapsed: 5us

builder - 100 - elapsed: 77us
concatenation - 100 - elapsed: 1669us
creation - 100 - elapsed: 43us

builder - 1000 - elapsed: 511us
concatenation - 1000 - elapsed: 111504us
creation - 1000 - elapsed: 282us

builder - 10000 - elapsed: 3364us 
concatenation - 10000 - elapsed: 5709793us
creation - 10000 - elapsed: 972us

Ohne Berücksichtigung der Ergebnisse für 1 Verkettung (JIT hat noch nicht seine Arbeit geleistet), ist selbst für 10 Verkettungen die Leistungsstrafe relevant. Bei Tausenden von Verkettungen ist der Unterschied enorm.

Die Lehren aus diesem sehr schnellen Experiment (mit dem obigen Code leicht reproduzierbar): Verwenden Sie niemals den +=, um Zeichenfolgen miteinander zu verknüpfen, selbst in sehr einfachen Fällen, in denen ein paar Verknüpfungen erforderlich sind (wie gesagt, das Erstellen neuer Zeichenfolgen ist ohnehin teuer) und übt Druck auf den GC aus).

7
Paolo Maresca

Apache Commons-Lang hat eine ToStringBuilder Klasse, die sehr einfach zu benutzen ist. Es erledigt einen netten Job, indem es sowohl die Append-Logik behandelt als auch formatiert, wie Ihr ToString aussehen soll.

public void toString() {
     ToStringBuilder tsb =  new ToStringBuilder(this);
     tsb.append("a", a);
     tsb.append("b", b)
     return tsb.toString();
}

Gibt eine Ausgabe zurück, die wie [email protected][a=whatever, b=foo] aussieht.

Oder in einer kondensierteren Form mit Verkettung:

public void toString() {
     return new ToStringBuilder(this).append("a", a).append("b", b").toString();
}

Oder wenn Sie die Reflektion verwenden möchten, um jedes Feld der Klasse einzuschließen:

public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

Sie können auch den Stil des ToStrings anpassen, wenn Sie möchten.

7
matt b

Machen Sie die toString-Methode so lesbar wie möglich!

Die einzige Ausnahme in meinem Buch ist, wenn Sie beweisen für mich, dass es erhebliche Ressourcen verbraucht :) (Ja, das bedeutet Profiling)

Beachten Sie auch, dass der Compiler Java 5 schneller Code generiert als der in früheren Java-Versionen verwendete handschriftliche Ansatz "StringBuffer". Wenn Sie "+" verwenden, sind diese und zukünftige Verbesserungen kostenlos.

Es scheint eine Debatte darüber zu geben, ob die Verwendung von StringBuilder mit aktuellen Compilern noch erforderlich ist. Also dachte ich, ich gebe meine 2 Cent Erfahrung.

Ich habe eine JDBC Ergebnismenge von 10.000 Datensätzen (ja, ich benötige alle Datensätze in einem Stapel.) Die Verwendung des Operators + dauert auf meinem Computer mit Java 1.8 ungefähr 5 Minuten. Die Verwendung von stringBuilder.append("") für dieselbe Abfrage dauert weniger als eine Sekunde.

Der Unterschied ist also riesig. Innerhalb einer Schleife ist StringBuilder viel schneller.

3
Eddy

In Bezug auf die Leistung ist die Verkettung von Zeichenfolgen mit '+' kostspieliger, da eine vollständig neue Kopie von Zeichenfolgen erstellt werden muss, da Zeichenfolgen in Java unveränderlich sind. Dies spielt insbesondere dann eine Rolle, wenn die Verkettung sehr häufig ist, z. B. innerhalb einer Schleife. Folgendes schlägt mein IDEA vor, wenn ich so etwas versuche:

enter image description here

Allgemeine Regeln:

  • Innerhalb einer einzelnen String-Zuweisung ist die Verwendung der String-Verkettung in Ordnung.
  • Wenn Sie eine Schleife ausführen, um einen großen Block von Zeichendaten aufzubauen, wählen Sie StringBuffer.
  • Die Verwendung von + = für einen String ist immer weniger effizient als die Verwendung eines StringBuffers, daher sollten Warnglocken geläutet werden. In bestimmten Fällen ist die erzielte Optimierung jedoch im Vergleich zu den Lesbarkeitsproblemen vernachlässigbar. Verwenden Sie also Ihren gesunden Menschenverstand.

Hier ist ein Netter Jon Skeet Blog um dieses Thema.

2
Sudip Bhandari

Siehe folgendes Beispiel:

//Java8
static void main(String[] args) {
    case1();//str.concat
    case2();//+=
    case3();//StringBuilder
}

static void case1() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str = str.concat(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case2() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    String str = "";
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str+=UUID.randomUUID()+"---";
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");
}

static void case3() {
    List<Long> savedTimes = new ArrayList();
    long startTimeAll = System.currentTimeMillis();
    StringBuilder str = new StringBuilder("");
    for (int i = 0; i < MAX_ITERATIONS; i++) {
        long startTime = System.currentTimeMillis();
        str.append(UUID.randomUUID()+"---");
        saveTime(savedTimes, startTime);
    }        
    System.out.println("Created string of length:"+str.length()+" in "+(System.currentTimeMillis()-startTimeAll)+" ms");

}

static void saveTime(List<Long> executionTimes, long startTime) {
        executionTimes.add(System.currentTimeMillis()-startTime);
        if(executionTimes.size()%CALC_AVG_EVERY == 0) {
            out.println("average time for "+executionTimes.size()+" concatenations: "+
                    NumberFormat.getInstance().format(executionTimes.stream().mapToLong(Long::longValue).average().orElseGet(()->0))+
                    " ms avg");
            executionTimes.clear();
        }
}

Ausgabe:

durchschnittliche Zeit für 10000 Verkettungen: 0,096 ms Durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,185 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,327 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,501 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,656 ms durchschn
Erstellte Zeichenfolge mit einer Länge von: 1950000 in 17745 ms
durchschnittliche Zeit für 10000 Verkettungen: 0,21 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,652 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 1,129 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 1,727 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 2,302 ms durchschn
Erstellte Zeichenfolge mit einer Länge von: 1950000 in 60279 ms
durchschnittliche Zeit für 10000 Verkettungen: 0,002 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,002 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,002 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,002 ms durchschn
durchschnittliche Zeit für 10000 Verkettungen: 0,002 ms durchschn
Erstellte Zeichenfolge mit einer Länge von: 1950000 in 100 ms

Mit zunehmender Länge der Zeichenfolge nimmt auch die Verkettungszeit zu.
Hier wird auf jeden Fall das StringBuilder benötigt.
Wie Sie sehen, wirkt sich die Verkettung: UUID.randomUUID()+"---" nicht wirklich auf die Zeit aus.

P.S.: Ich glaube nicht, dass wann man StringBuilder in Java verwendet wirklich ein Duplikat davon ist.
In dieser Frage geht es um toString(), bei dem meist keine Verkettung großer Zeichenfolgen durchgeführt wird.

2
Marinos An

Kann ich darauf hinweisen, dass Sie, wenn Sie eine Sammlung durchlaufen und StringBuilder verwenden, vielleicht Apache Commons Lang und StringUtils.join () (in verschiedene Geschmacksrichtungen)?

Unabhängig von der Leistung sparen Sie sich das Erstellen von StringBuildern und for-Schleifen für das millionste Mal.

1
Brian Agnew

Ich habe vier verschiedene Ansätze verglichen, um die Leistung zu vergleichen. Ich weiß nicht genau, was mit gc passiert, aber das Wichtigste für mich ist die Zeit. Der Compiler ist hier ein wichtiger Faktor. Ich habe jdk1.8.0_45 unter der Windows 8.1-Plattform verwendet.

concatWithPlusOperator = 8
concatWithBuilder = 130
concatWithConcat = 127
concatStringFormat = 3737
concatWithBuilder2 = 46


public class StringConcatenationBenchmark {

private static final int MAX_LOOP_COUNT = 1000000;

public static void main(String[] args) {

    int loopCount = 0;
    long t1 = System.currentTimeMillis();
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithPlusOperator();
        loopCount++;
    }
    long t2 = System.currentTimeMillis();
    System.out.println("concatWithPlusOperator = " + (t2 - t1));

    long t3 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder();
        loopCount++;
    }
    long t4 = System.currentTimeMillis();
    System.out.println("concatWithBuilder = " + (t4 - t3));

    long t5 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithConcat();
        loopCount++;
    }
    long t6 = System.currentTimeMillis();
    System.out.println("concatWithConcat = " + (t6 - t5));

    long t7 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatStringFormat();
        loopCount++;
    }
    long t8 = System.currentTimeMillis();
    System.out.println("concatStringFormat = " + (t8 - t7));

    long t9 = System.currentTimeMillis();
    loopCount = 0;
    while (loopCount < MAX_LOOP_COUNT) {
        concatWithBuilder2();
        loopCount++;
    }
    long t10 = System.currentTimeMillis();
    System.out.println("concatWithBuilder2 = " + (t10 - t9));
}

private static void concatStringFormat() {
    String s = String.format("%s %s %s %s ", "String", "String", "String", "String");
}

private static void concatWithConcat() {
    String s = "String".concat("String").concat("String").concat("String");
}

private static void concatWithBuilder() {
    StringBuilder builder=new StringBuilder("String");
    builder.append("String").append("String").append("String");
    String s = builder.toString();
}

private static void concatWithBuilder2() {
    String s = new StringBuilder("String").append("String").append("String").append("String").toString();
}

private static void concatWithPlusOperator() {
    String s = "String" + "String" + "String" + "String";
}
}
1
Hamedz

Folgendes habe ich in Java8 überprüft

  • String-Verkettung verwenden
  • StringBuilder verwenden

    long time1 = System.currentTimeMillis();
    usingStringConcatenation(100000);
    System.out.println("usingStringConcatenation " + (System.currentTimeMillis() - time1) + " ms");
    
    time1 = System.currentTimeMillis();
    usingStringBuilder(100000);
    System.out.println("usingStringBuilder " + (System.currentTimeMillis() - time1) + " ms");
    
    
    private static void usingStringBuilder(int n)
    {
        StringBuilder str = new StringBuilder();
        for(int i=0;i<n;i++)
            str.append("myBigString");    
    }
    
    private static void usingStringConcatenation(int n)
    {
        String str = "";
        for(int i=0;i<n;i++)
            str+="myBigString";
    }
    

Es ist wirklich ein Albtraum, wenn Sie eine Zeichenfolgenverkettung für eine große Anzahl von Zeichenfolgen verwenden.

usingStringConcatenation 29321 ms
usingStringBuilder 2 ms
0
nagendra547