Vorwort
Unter den Java -Entwicklern ist die hohe Ressourcenbelegung von Saiten oft ein heißes Thema.
Lassen Sie uns eingehend diskutieren, warum es hohe Ressourcen einnimmt.
In Java ist ein String -Objekt unveränderlich, was bedeutet, dass Sie es nach dem Erstellen nicht mehr ändern können. Wenn wir Strings spleißen, erstellen wir eine neue Schnur und der alte wird vom Müllsammler gekennzeichnet.
Wenn wir Millionen von Saiten verarbeiten, erzeugen wir Millionen zusätzlicher Zeichenfolgen, die vom Müllsammler bearbeitet werden sollen.
In den meisten Tutorials sehen Sie möglicherweise, dass die Verwendung von + Zeichen zum Spleißzeichenfolgen mehrere Zeichenfolgen erzeugt, was zu einer schlechten Leistung führt. Es wird empfohlen, StringBuffer/StringBuilder zum Spleiß zu verwenden.
Aber ist das wirklich der Fall?
Dieser Artikel hat das folgende Experiment in JDK8 durchgeführt:
public static void main (String [] args) {String result = ""; Ergebnis += "Einige weitere Daten"; System.out.println (Ergebnis); }Entschlüsseln durch Javap -c, um zu bekommen:
Code: 0: ALOAD_0 // Push 'this' auf den Stack 1: Invokespecial #1 // Invoke -Objektklasse Konstruktor // pop 'this' Ref aus dem Stack 4: return // Rückkehr aus dem Konstruktor Public static void Main (Java.lang.String []); Code: 0: LDC #2 // Konstante Nr. 2 in den Stack 2: store_1 // Lokale var aus Stack erstellen (Pop #2) 3: neu #3 // Push New StringBuilder Ref auf Stack 6: Dup // Duplicate Value Wert auf dem Stack 7: ALOADEPECIAL #4 // Invoke -Stingbuilder -Konstruktor // Pop -Objekt -Referenz 10: ALOAD_1 // Lokalablenken. invokeVirtual #5 // Invoke -Methode StringBuilder.append () // Pop -Obj -Referenz + Parameter // Push -Ergebnis (StringBuilder Ref) 14: LDC #6 // Push "ein paar weitere Daten" auf dem Stack 16: InvokeVirtual #5 // InvokeBuilder.append // Pope -Ergebnis: InvokeVirtual #7 // InvokeBuilder.append // Push -Ergebnis 19: Invokevical #7 // InvokeBuilder.TOsstRIGUS. 22: Store_1 // Lokale var aus Stack erstellen (Pop #6) 23: GetStatic #8 // Push Value System.out: PrintStream 26: ALOAD_1 // Push lokale Variable, die #6 27 enthalten: invokevirtual #9 // Invoke -Methode PrintStream.println () // Pop zweimal (Object Ref + Parameter) 30: Rückkehr // zurück -VOID VOID VOID VOID VOID VOID VOID VOID VOID.
Sie können sehen, dass der Java -Compiler den generierten Bytecode optimiert, automatisch einen StringBuilder erstellt und Anhangvorgänge ausführt.
Da die Substrings der endgültigen Zeichenfolge bereits zur Kompilierungszeit bekannt sind, führt der Java -Compiler in diesem Fall die obige Optimierung durch. Diese Optimierung wird als statische String -Verkettungsoptimierung bezeichnet und seit JDK5 aktiviert.
Bedeutet das, dass wir nach JDK5 StringBuilder nicht mehr manuell generieren müssen und über das + Zeichen dieselbe Leistung erzielen können?
Versuchen wir dynamisch Spleißen von Zeichenfolgen:
Dynamische Spleißzeichenfolgen beziehen sich auf Substrings, die nur zur Laufzeit bekannt sind. Zum Beispiel eine Zeichenfolge zu einer Schleife hinzufügen:
public static void main (String [] args) {String result = ""; für (int i = 0; i <10; i ++) {result+= "Einige weitere Daten"; } System.out.println (Ergebnis); }Auch zerlegt:
Code: 0: ALOAD_0 // Push 'this' auf den Stack 1: Invokespecial #1 // Invoke -Objektklasse Konstruktor // pop 'this' Ref aus dem Stack 4: return // Rückkehr aus dem Konstruktor Public static void Main (Java.lang.String []); Code: 0: ldc #2 // Load constant #2 on to the stack 2: store_1 // Create local var from stack, pop #2 3: iconst_0 // Push value 0 onto the stack 4: istore_2 // Pop value and store it in local var 5: iload_2 // Push local var 2 on to the stack 6: i2d // Convert int to double on // top of stack (pop + push) 7: LDC2_W #3 // Konstante 10E6 auf den Stapel 10: DCMPG // zwei Doppel über den Stapel vergleiche // Pop -Ergebnis: -1, 0 oder 1 11: IFGE 40 // Wenn der Wert auf dem Stapel der Stapel auf dem Stapel größer ist, ist der Stapel. Der Stack 18: Invokespecial #6 // Invoke StringBuilder -Konstruktor // Pop -Objektreferenz 21: ALOAD_1 // Lokale var 1 (leere Zeichenfolge) // auf den Stack 22: invokevirtual #7 // aufgerufen Stringbuilder StringBuilder.Append // Pop OBJ Ref + Param, Push -Ergebnis 30: InvokeVirtual #9 // Invoke StringBuilder.toString // Pop -Objektreferenz 33: Store_1 // Lokale var aus Stack erstellen (Pop) 34: iinc 2, 1 // Lokale Variable 2 // Drucken. ALOAD_1 // Lokale var 1 (Ergebniszeichenfolge) 44: InvokeVirtual #11 // Invoke -Methode printstream.println () // zweimal Pop (Objekt Ref + Parameter) 47: Return // Reserve void aus der Methode
Sie können sehen, dass der Stringbuilder mit 14 neu war, aber mit 37, GOTO 5. Während der Schleife wurde die Optimierung nicht erreicht, und neue Stringbuilder wurden ständig generiert.
Der obige Code ist also ähnlich:
String result = ""; für (int i = 0; i <10; i ++) {StringBuilder tmp = new StringBuilder (); tmp.Append (Ergebnis); tmp.Append ("Einige weitere Daten"); result = tmp.toString ();} System.out.println (Ergebnis);Sie können sehen, dass neue Stringbuilder ständig erzeugt werden, und durch das ToString wird der ursprüngliche StringBuilder nicht mehr als Müll verwiesen und erhöht auch die GC -Kosten.
Daher verwenden Sie in der tatsächlichen Verwendung, wenn Sie nicht unterscheiden können, ob eine Zeichenfolge statisch oder dynamisch ist, StringBuilder.
Referenz:
http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.