Mai mult
Concatenarea șirurilor: concat() vs "+" operator
Presupunând că Șirul a și b:
a += b
a = a.concat(b)
Sub capota, sunt același lucru?
Aici este concat decompilat ca referință. Am'd place să fie în măsură să separe " + " de operator, precum și pentru a vedea ce face.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
475
11
Nu, nu chiar.
În primul rând, nu's o ușoară diferență în semantica. Dacă " a "este
nul", apoi " un.concat(b)
aruncă oNullPointerException " dar "o+=b
va trata valoarea inițială a" a " ca și cum ar finull
. Pe de altă parte, concat()metoda acceptă numai "String" valori în timp ce pe " + " operator tăcere converti argument un Șir de caractere (folosind
toString () metoda pentru obiecte). Deciconcat()
metoda este mult mai strictă în ceea ce-l acceptă.Să se uite sub capota, scrie o clasă simplă cu
a += b;
Acum demontați cu javap -c (inclus în Sun JDK). Ar trebui să vedeți o listă, inclusiv:
Deci,
o += b
este echivalentul aAnii
concat
metodă ar trebui să fie mai rapid. Cu toate acestea, cu mai multe siruri de caractere de laStringBuilder
metoda victorii, cel puțin în termeni de performanță.Codul sursă al
String
siStringBuilder
(și ambalajul său-private în clasa de bază) este disponibil în src.zip de Soare JDK. Puteți vedea că sunteți construirea o matrice char (redimensionare după cum este necesar) și apoi a aruncat-o departe, atunci când vă creați finalString
. În practica de alocare de memorie este surprinzător de repede.Actualizare: Ca Pawel Adamski note, performanta s-a schimbat în ultimii HotSpot.
javac încă produce exact același cod, dar bytecode compiler ieftin. Simplu de testare în întregime eșuează pentru că întregul corp de cod este aruncat. Însumarea Sistem.identityHashCode
(nuȘir de caractere.hashCode
) aratăStringBuffer
cod are un ușor avantaj. Supuse de a modifica atunci când următoarea actualizare este lansat, sau dacă utilizați un alt JVM. Din @lukaseder, o listă de HotSpot JVM intrinsics.Niyaz este corect, dar's, de asemenea, demn de remarcat faptul că în special operatorul + poate fi transformat în ceva mult mai eficient de către compilatorul Java. Java are un StringBuilder clasă care reprezintă un non-thread-safe, mutabil Șir. Atunci când se efectuează o grămadă de Șir înlănțuirilor, Java compiler în tăcere convertește
în
care pentru siruri de caractere mari este semnificativ mai eficient. Din câte știu, acest lucru nu se întâmplă atunci când utilizați metoda concat.
Cu toate acestea, metoda concat este mult mai eficient atunci când este concatenarea unui Șir gol pe un Șir existente. În acest caz, JVM nu are nevoie pentru a crea un nou obiect String și puteți întoarce pur și simplu cel existent. A se vedea la concat documentația pentru a confirma acest lucru.
Deci, dacă te're super-preocupat de randament atunci ar trebui să utilizați metoda concat când concatenarea eventual-Siruri de caractere goale, și de a folosi + în caz contrar. Cu toate acestea, diferenta de performanta ar trebui să fie neglijabil și nu ar trebui't vă faceți griji vreodată despre asta.
Am dat un test similar ca @marcio, dar cu următoarea buclă în loc:
Doar pentru o bună măsură, m-am aruncat în `StringBuilder.append (), la fel de bine. Fiecare test a fost rulat de 10 ori, cu 100 de mii de repetari pentru fiecare serie. Aici sunt rezultatele:
StringBuilder
pune mâinile în jos. Ceas de timp rezultatul a fost 0 pentru cel mai execută, iar cele mai lungi luat 16ms.o += b
ia despre 40000ms (40 de ani) pentru fiecare termen.concat
necesită doar 10000ms (10s) pe fugă.Nu am't decompilat clasa pentru a vedea interne sau rulați-l prin profiler încă, dar bănuiesc că
a += b
petrece mare parte din timp, crearea de noi obiecte de StringBuilderși apoi de a le converti înapoi la
String`.Cele mai multe răspunsuri aici sunt din 2008. Se pare că lucrurile s-au schimbat de-a lungul timpului. Ultimul meu referință realizate cu JMH arată că pe Java 8
+
este de aproximativ două ori mai repede decâtconcat
.Meu de referință:
Rezultate:
Tom este corect în a descrie exact ceea ce operatorul + are. Se creează temporar un
StringBuilder
, adaugă părți, și se termină cutoString()
.Cu toate acestea, toate răspunsurile de până acum sunt ignorând efectele HotSpot runtime optimizări. În mod specific, aceste temporar operațiunile sunt recunoscute ca un model comun și sunt înlocuite cu altele mai eficiente cod mașină la run-time.
@marcio: Te'am creat o micro-referință; cu moderne JVM's nu este un mod valabil de la profil cod.
Motivul run-time de optimizare contează este că multe dintre aceste diferențe în cod-chiar inclusiv-obiect crearea -- sunt complet diferite odată HotSpot se întâmplă. Singura modalitate de a ști sigur este profilare codul in situ.
În cele din urmă, toate aceste metode sunt, de fapt, incredibil de rapid. Acest lucru ar putea fi un caz de nastere prematura de optimizare. Dacă aveți un cod care concatenează șiruri de un lot, mod de a obține viteza maximă, probabil, nu are nimic de-a face cu care operatorii le alegeți și în loc algoritmul tu're folosind!
Ce zici de niște simple de testare? Folosit codul de mai jos:
Testat de mai multe ori. Anii
concat()
versiune de execuție a luat jumătate din timp, în medie.Acest rezultat m-a surprins pentru că
concat()
metoda creează întotdeauna o nouă string (returnează un " nou String(rezultat)`". L's bine cunoscut faptul că:De ce a fost't compilator capabil de a optimiza șir de creație în "a + b" codul, știind că a condus întotdeauna la același șir? S-ar putea evita un nou șir de creație. Dacă tu nu't cred că afirmația de mai sus, testul pentru sine dumneavoastră.
Practic, există două diferențe importante între + și
concat
metoda.De Exemplu:
String s = 10 + "Buna ziua";
În acest caz, rezultatul ar trebui să fie 10Hello.
String s = "I"; String s1 = s.concat("sunt").concat("bun").concat("baiat"); Sistem.afară.println(s1);
În cazul de mai sus, trebuie să furnizeze două șiruri obligatorie.
Cazul 1: Să presupunem că am concat aceleași sfori cu concat operatorul în acest fel
String s="I"; String s1=s.concat("sunt").concat("bun").concat("baiat"); Sistem.afară.println(s1);
În acest caz numărul total de obiecte create în piscină sunt 7 astfel:
Am sunt buna băiatul Iam Iamgood Iamgoodboy
Cazul 2:
Acum am de gând să concatinate același siruri de via + operatorul
String s="I"+"sunt"+"bun"+"baiat"; Sistem.afară.println(s);
În cazul de mai sus, numărul total de obiecte create sunt doar 5.
De fapt, atunci când ne-am concatinate siruri de caractere via + operatorul de atunci se menține o clasa StringBuffer pentru a efectua aceeași sarcină, după cum urmează:-
StringBuffer sb = new StringBuffer("I"); sb.append("sunt"); sb.append("bun"); sb.append("baiat"); Sistem.afară.println(sb);
În acest fel se va crea doar cinci obiecte.
Deci tipii ăștia sunt diferențele de bază între + și concat metoda. Bucurați-vă de :)
Pentru motive de exhaustivitate, am vrut să adaug că definiția '+' operator pot fi găsite în JLS SE8 15.18.1:
Despre punerea în aplicare JLS spune următoarele:
Deci, judecând din 'un compilatorul Java poate folosi clasa StringBuffer sau o tehnică similară pentru a reduce', diferite compilatoare ar putea produce diferite byte-code.
La operatorul + ** poate lucra între un șir de caractere și un string, char, integer, double sau float date de tip valoare. Doar convertește valoarea acestuia reprezentare șir înainte de concatenare.
La concat operator poate fi făcut și cu siruri de caractere. Se verifică pentru tipul de date de compatibilitate și aruncă o eroare, dacă ei nu't de meci.
Cu excepția acest lucru, codul furnizat face aceleasi lucruri.
Eu nu't cred.
o.concat(b) este implementat în Șir și cred că punerea în aplicare n't se schimba prea mult de la începutul java masini. Butonul " + " operațiunea de punere în aplicare depinde de versiune Java și compilator. În prezent, " + " este implementat folosind [
StringBuffer][1] pentru a face operația cât mai repede posibil. Poate că în viitor, acest lucru se va schimba. În versiunile mai vechi de java
+` operațiune pe Siruri de caractere a fost mult mai lent ca a produs rezultate intermediare.Cred că
+=
este implementat folosind " + " și în mod similar optimizat.Atunci când se utilizează +, viteza scade ca string's lungimea crește, dar atunci când se utilizează concat, viteza este mult mai stabil, și cea mai bună opțiune este utilizarea StringBuilder clasa care are viteză stabilă, în scopul de a face asta.
Cred că puteți înțelege de ce. Dar cel mai bun mod pentru crearea de șiruri lungi este folosind StringBuilder() și append(), fie viteza va fi inacceptabil.