Java: String concat vs StringBuilder-zoptymalizowany, więc co powinienem zrobić?

W Ta odpowiedź mówi (implikuje), że string concatenation jest zoptymalizowany do operacji StringBuilder i tak, więc kiedy piszę mój kod, czy jest jakiś powód, aby napisać kod StringBuilder w źródle? Zauważ, że mój przypadek użycia różni się od pytania OP, ponieważ łączę/dołączam setki-tysiące linii.

Żeby było jaśniej: zdaję sobie sprawę z różnic każdego z nich, chodzi tylko o to, że nie wiem, czy warto pisać kod StringBuilder ponieważ jest mniej czytelny i kiedy jego rzekomo wolniejszy kuzyn, Klasa String, i tak jest konwertowana automagicznie w procesie kompilacji.

Author: Community, 2013-02-18

4 answers

Myślę, że użycie StringBuilder vs + naprawdę zależy od kontekstu, w którym go używasz.

Ogólnie używając JDK 1.6 i nowszych kompilator automatycznie połączy łańcuchy znaków używając StringBuilder.

String one = "abc";
String two = "xyz";
String three = one + two;

To skompiluje String three jako:

String three = new StringBuilder().append(one).append(two).toString();

Jest to bardzo pomocne i oszczędza nam trochę czasu. Jednak proces ten nie zawsze jest optymalny. Weźmy na przykład:

String out = "";
for( int i = 0; i < 10000 ; i++ ) {
    out = out + i;
}
return out;

Jeśli skompilujemy do kodu bajtowego, a następnie dekompilujemy wygenerowany bajt, otrzymamy coś like:

String out = "";
for( int i = 0; i < 10000; i++ ) {
    out = new StringBuilder().append(out).append(i).toString();
}
return out;

Kompilator zoptymalizował wewnętrzną pętlę, ale z pewnością nie dokonał najlepszych możliwych optymalizacji. Aby ulepszyć nasz kod możemy użyć:

StringBuilder out = new StringBuilder();
for( int i = 0 ; i < 10000; i++ ) {
    out.append(i);
}
return out.toString();

Teraz jest to bardziej optymalne niż kod generowany przez kompilator, więc zdecydowanie istnieje potrzeba pisania kodu za pomocą StringBuilder/StringBuffer klasy w przypadkach, gdy potrzebny jest efektywny kod. Obecne Kompilatory nie radzą sobie z łączeniem łańcuchów w pętle, jednak może to się zmienić w przyszłości.

Potrzebujesz aby dokładnie sprawdzić, gdzie trzeba ręcznie zastosować StringBuilder i spróbować użyć go tam, gdzie nie zmniejszy to czytelności kodu.

Uwaga: skompilowałem kod używając JDK 1.6 i zdekompilowałem kod używając programu javap, który wypluwa kod bajtowy. Jest to dość łatwe do zinterpretowania i często jest użytecznym odniesieniem do optymalizacji kodu. Kompilator zmienia kod za kulisami, więc zawsze jest interesujące zobaczyć, co robi!

 108
Author: Tom Cammann,
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
2014-05-02 11:04:51

Kluczową frazą w twoim pytaniu jest "podobno wolniejszy". Musisz określić, czy jest to rzeczywiście wąskie gardło, a następnie sprawdzić, które jest szybsze.

Jeśli masz zamiar napisać ten kod, ale jeszcze go nie napisałeś, napisz to, co jest dla Ciebie jaśniejsze, a w razie potrzeby sprawdź, czy jest to wąskie gardło.

Chociaż sensowne jest używanie kodu, który uważasz za szybszy, jeśli oba są równie czytelne, w rzeczywistości zajmuje to trochę czasu, aby dowiedzieć się, który jest szybszy, gdy nie masz potrzeba to strata czasu. Czytelność powyżej wydajności, dopóki wydajność nie jest niedopuszczalna.

 3
Author: jmoreno,
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
2013-02-18 00:20:34

To zależy od przypadku, ale StringBuilder uważa się za nieco szybszy. Jeśli robisz konkatenację wewnątrz pętli, sugerowałbym użycie StringBuilder.

W każdym razie radzę ci profilować i porównywać swój kod (jeśli robisz tak ogromny dodatek).

Bądź ostrożny: instancje StringBuilder są mutowalne i nie mogą być dzielone między wątki (chyba że naprawdę wiesz, co robisz.) w przeciwieństwie do ciągów, które są niezmienne.

 2
Author: bssstudio,
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
2013-02-18 00:09:38

Mogłem źle zrozumieć twoje pytanie, ale StringBuilder jest szybszy podczas dodawania ciągów. Tak więc, jeśli dodajesz "setki-tysiące linii", zdecydowanie powinieneś użyć StringBuilder (lub StringBuffer, jeśli używasz wielowątkowej aplikacji).

(dokładniejsza odpowiedź w komentarzach)

 0
Author: cldjr,
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
2013-02-18 00:18:07