StringBuilder vs string concatenation w ToString () w Javie

Biorąc pod uwagę 2 toString() implementacje poniżej, która z nich jest preferowana:

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

Lub

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

?

Co ważniejsze, biorąc pod uwagę, że mamy tylko 3 właściwości, może to nie zrobić różnicy, ale w którym momencie można przełączyć się z + concat na StringBuilder?

Author: medvedev1088, 2009-10-07

18 answers

Wersja 1 jest preferowana, ponieważ jest krótsza i kompilator zmieni ją w wersję 2 - bez żadnej różnicy w wydajności.

Ważniejsze biorąc pod uwagę, że mamy tylko 3 właściwości może nie zrobić różnica, ale w jakim momencie przejście z concat do builder?

W miejscu łączenia w pętlę - zwykle wtedy kompilator nie może sam zastąpić StringBuilder.

 831
Author: Michael Borgwardt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-09 14:18:56

Najważniejsze jest to, czy piszesz pojedynczą konkatenację w jednym miejscu, czy kumulujesz ją w czasie.

Dla przykładu, który podałeś, nie ma sensu jawnie używać Stringbuildera. (Spójrz na skompilowany kod dla Twojego pierwszego przypadku.)

Ale jeśli budujesz łańcuch np. wewnątrz pętli, użyj StringBuilder.

Aby wyjaśnić, zakładając, że hugeArray zawiera tysiące ciągów, kod taki:

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

Jest bardzo marnowanie czasu i pamięci w porównaniu z:

...
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();
 211
Author: joel.neely,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 15:47:43

Wolę:

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

...ponieważ jest krótki i czytelny.

Ja bym nie optymalizował to pod kątem prędkości, chyba że użyjesz go wewnątrz pętli z bardzo dużą liczbą powtórzeń i zmierzyłbym różnicę wydajności.

Zgadzam się, że jeśli musisz wypisać wiele parametrów, ten formularz może być mylący (jak mówi jeden z komentarzy). W tym przypadku przełączyłbym się na bardziej czytelną formę (być może używając ToStringBuilder z apache-commons-zaczerpniętego z odpowiedź Matta b) i ponownie zignorować wydajność.

 66
Author: tangens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 23:32:26

W większości przypadków nie zobaczysz rzeczywistej różnicy między tymi dwoma podejściami, ale łatwo jest skonstruować najgorszy scenariusz, taki jak ten:

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+="*";
    }
}

Wyjście To:

slow elapsed 11741 ms
fast elapsed 7 ms

Problem polega na tym, że dołączenie += do łańcucha rekonstruuje nowy łańcuch, więc to kosztuje coś liniowego do długości łańcuchów (suma obu).

Więc - do twojego pytania:

Drugie podejście byłoby szybsze, ale jest mniej czytelne i trudniejsze do utrzymania. Jak już mówiłem, w Twoim konkretny przypadek prawdopodobnie nie widać różnicy.
 58
Author: Omry Yadan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-12 09:38:51

Miałem również sprzeczkę z moim szefem na temat tego, czy używać append czy +. ponieważ używają Append (nadal nie mogę dowiedzieć się, jak mówią za każdym razem, gdy tworzony jest nowy obiekt). Więc pomyślałem, aby zrobić trochę R & D. chociaż kocham Michael Borgwardt explaination ale po prostu chciałem pokazać Wyjaśnienie, jeśli ktoś będzie naprawdę musiał wiedzieć w przyszłości.

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

I demontaż powyższej klasy wychodzi jako

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

Z powyższych dwóch kodów widać, że Michael jest right.In każdy przypadek tylko jeden SB obiekt jest tworzony.

 27
Author: perilbrain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-03 23:51:10

Od wersji Java 1.5, prosta jednolinijkowa konkatenacja z " + " i StringBuilder.append () generuje dokładnie ten sam bajt.

Więc ze względu na czytelność kodu, użyj "+".

2 wyjątki:

  • środowisko wielowątkowe: StringBuffer
  • konkatenacja w pętlach: StringBuilder / StringBuffer
 24
Author: Zofren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 09:54:36

Używając najnowszej wersji Javy(1.8) the disassembly (javap -c) pokazuje optymalizację wprowadzoną przez kompilator. + jak również sb.append() wygeneruje bardzo podobny kod. Warto jednak sprawdzić zachowanie, jeśli używamy + W pętli for.

Dodawanie ciągów za pomocą + w pętli for

Java:

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

ByteCode: (for fragment pętli)

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

Dodawanie ciągów za pomocą stringbuilder.Dołącz

Java:

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

ByteCdoe: (for fragment pętli)

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

Jest jednak trochę rażącej różnicy . W pierwszym przypadku, gdzie użyto +, dla każdej iteracji pętli for tworzony jest nowy StringBuilder, a wygenerowany wynik jest przechowywany przez wywołanie toString() (od 29 do 41). Generujesz więc Łańcuchy pośrednie, których naprawdę nie potrzebujesz podczas używania operatora + W pętli for.

 20
Author: ring bearer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-26 08:12:10

Apache Commons-Lang posiada klasę ToStringBuilder, która jest bardzo łatwa w użyciu. Wykonuje dobrą robotę zarówno w obsłudze logiki dołączania, jak i formatowaniu tego, jak chcesz, aby twój toString wyglądał.

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

Zwróci wyjście, które wygląda jak com.blah.YourClass@abc1321f[a=whatever, b=foo].

Lub w bardziej skondensowanej formie za pomocą łańcucha:

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

Lub jeśli chcesz użyć reflection, aby dołączyć każde pole klasy:

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

Możesz również dostosować styl ToString, jeśli chcesz.

 7
Author: matt b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 16:57:01

Ze względów wydajnościowych, stosowanie += (String konkatenacja) jest zniechęcana. Powodem tego jest: Java String jest niezmienna, za każdym razem, gdy zostanie wykonana nowa konkatenacja, tworzony jest nowy String (Nowy ma inny odcisk palca od starszego już w Puli łańcuchów ). Tworzenie nowych łańcuchów wywiera presję na GC i spowalnia program: tworzenie obiektów jest kosztowne.

Poniższy kod powinien uczynić go bardziej praktycznym i przejrzystym jednocześnie.

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

Wyniki dla biegu przedstawiono poniżej.

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

Nie biorąc pod uwagę wyników za 1 konkatenację (JIT jeszcze nie wykonał swojej pracy), nawet dla 10 konkatenacji kara za wykonanie jest istotna; dla tysięcy konkatenacji różnica jest ogromna.

Wnioski wyciągnięte z tego bardzo szybkiego eksperymentu( łatwo odtwarzalnego za pomocą powyższego kodu): nigdy nie używaj += do łączenia łańcuchów ze sobą, nawet w bardzo podstawowych przypadkach, gdy kilka konkatenacji jest potrzebne (jak już wspomniano, tworzenie nowych ciągów i tak jest drogie i wywiera presję na GC).

 7
Author: Paolo Maresca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-18 20:14:33

W Javie 9 Wersja 1 powinna być szybsza, ponieważ jest konwertowana na wywołanie invokedynamic. Więcej szczegółów można znaleźć w JEP-280:

Chodzi o zastąpienie całego Stringbuildera append dance prostym wywołaniem wywołania w Javie.lang./ align = "left" / StringConcatFactory, który przyjmie wartości w potrzebie konkatenacji.

 7
Author: ZhekaKozlov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 00:53:52

Spraw, aby metoda toString była jak najbardziej czytelna!

Jedynym wyjątkiem w mojej książce jest to, czy możesz udowodnić mi, że zużywa znaczne zasoby :) (tak, oznacza to profilowanie)

Należy również zauważyć, że kompilator Java 5 generuje szybszy Kod niż Odręczne podejście "StringBuffer" używane we wcześniejszych wersjach Javy. Jeśli używasz " + " to i przyszłe ulepszenia są dostępne za darmo.

 4
Author: Thorbjørn Ravn Andersen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 19:05:23

Wydaje się, że istnieje dyskusja, czy używanie Stringbuildera jest nadal potrzebne w obecnych kompilatorach. Więc pomyślałem, że dam swoje 2 centy doświadczenia.

Mam JDBC zestaw wyników 10K rekordów (tak, potrzebuję ich wszystkich w jednej partii.) Korzystanie z operatora + zajmuje około 5 minut na mojej maszynie z Java 1.8. Użycie stringBuilder.append("") zajmuje mniej niż sekundę dla tego samego zapytania.

Więc różnica jest ogromna. Wewnątrz pętli StringBuilder jest znacznie szybciej.
 3
Author: Eddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-24 09:45:38

Zobacz przykład poniżej:

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

Wyjście:

Średni czas dla 10000 konkatenacji: 0.096 ms avg
średni czas dla 10000 konkatenacji: 0.185 ms avg
średni czas dla 10000 konkatenacji: 0.327 ms avg
średni czas dla 10000 konkatenacji: 0.501 ms avg
średni czas dla 10000 konkatenacji: 0.656 ms avg
Utworzony ciąg o długości: 1950000 w 17745 ms
średni czas dla 10000 konkatenacji: 0.21 ms avg
średni czas dla 10000 konkatenacji: 0.652 ms avg
średni czas dla 10000 konkatenacji: 1.129 ms avg
średni czas dla 10000 konkatenacji: 1.727 ms avg
średni czas dla 10000 konkatenacji: 2.302 ms avg
Utworzony ciąg o długości: 1950000 w 60279 ms
średni czas dla 10000 konkatenacji: 0.002 ms avg
średni czas dla 10000 konkatenacji: 0.002 ms avg
średni czas dla 10000 konkatenacji: 0.002 ms avg
średni czas dla 10000 konkatenacji: 0.002 ms avg
średni czas dla 10000 konkatenacji: 0.002 ms avg
Utworzony ciąg o długości: 1950000 w 100 ms

Wraz ze wzrostem długości łańcucha wzrasta również czas konkatenacji.
To jest miejsce, gdzie StringBuilder jest zdecydowanie potrzebne.
Jak widzicie, konkatenacja: UUID.randomUUID()+"---", tak naprawdę nie wpływa na czas.

P. S.: nie wydaje mi się kiedy używać Stringbuildera w Javie to naprawdę duplikat tego.
To pytanie mówi o toString(), który w większości przypadków nie wykonuje konkatenacji wielkich strun.

 2
Author: Marinos An,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-14 11:58:22

Czy mogę zauważyć, że jeśli zamierzasz iterować nad kolekcją i używać Stringbuildera, możesz chcieć sprawdzić Apache Commons Lang i StringUtils.join () (w różnych smakach) ?

Niezależnie od wydajności, zaoszczędzi to konieczności tworzenia Stringbuilderów i pętli przez co wydaje się, że milionowa czas.

 1
Author: Brian Agnew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 16:02:37

Porównałem cztery różne podejścia do porównania wydajności. Dokładnie Nie wiem, co się dzieje z gc, ale dla mnie najważniejszy jest czas. Kompilator jest tutaj ważnym czynnikiem.Użyłem jdk1.8. 0_45 pod platformą window8. 1.

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
Author: Hamedz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-09 19:06:23

Performance wise String concatenation using ' + ' is costeler because it mus to make a whole new copy of String since Strings are immutable in java. Odgrywa to szczególną rolę, jeśli konkatenacja jest bardzo częsta, np.: wewnątrz pętli. Oto, co sugeruje mój pomysł, gdy próbuję zrobić coś takiego:

Tutaj wpisz opis obrazka

Zasady Ogólne:

  • W ramach pojedynczego przypisania łańcuchów, użycie konkatenacji łańcuchów jest w porządku.
  • jeśli zapętlasz się, aby zbudować duży blok danych znaków, przejdź do StringBuffer.
  • używanie += na sznurku zawsze będzie mniej wydajne niż używanie Stringbuffera, więc powinno dzwonić ostrzegawczo - ale w niektórych przypadkach uzyskana Optymalizacja będzie znikoma w porównaniu z problemami z czytelnością, więc używaj zdrowego rozsądku.

Oto miły Jon Skeet blog wokół tego tematu.

 1
Author: Sudip Bhandari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-04 06:58:46

Do takich prostych ciągów wolę używać

"string".concat("string").concat("string");

W kolejności, powiedziałbym, że preferowaną metodą konstruowania ciągu jest użycie StringBuilder, String#concat (), a następnie przeciążony operator+. StringBuilder to znaczący wzrost wydajności podczas pracy z dużymi ciągami, podobnie jak użycie operatora + to duży spadek wydajności(wykładniczo duży spadek wraz ze wzrostem rozmiaru ciągów). Jedyny problem z używaniem .concat() jest to, że może rzucać NullPointerExceptions.

 -3
Author: Droo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-07 16:11:39

Myślę, że powinniśmy zastosować podejście StringBuilder append. Reason is

  1. String concatenate utworzy za każdym razem nowy obiekt string (ponieważ String jest obiektem niezmiennym), więc wytworzy 3 obiekty.

  2. W String builderze zostanie utworzony tylko jeden obiekt [StringBuilder jest muttable] , a dalszy ciąg zostanie do niego dołączony.

 -3
Author: VishalTambe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 00:42:38