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.
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!
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.
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.
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)
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