Eine andere Frage: Warum verwenden Sie einen SB nur für eine Iteration der Schleife? Gibt es eine andere innere Iteration? SB ist nicht wert, wenn Sie einfach A + B + C + D ausführen möchten (der Java-Compiler verwendet intern einen SB). Es ist hilfreich, wenn Sie Teile von Zeichenfolgen bedingt hinzufügen möchten, aber ansonsten ... verwenden Sie einfach "+".
Helios
Antworten:
135
Eine Möglichkeit besteht darin, die Löschmethode wie folgt zu verwenden:
StringBuffer sb =newStringBuffer();for(int n =0; n <10; n++){
sb.append("a");// This will clear the buffer
sb.delete(0, sb.length());}
Eine andere Option (Bit Cleaner) verwendet setLength (int len) :
Etwas weniger Müll wäre, einfach den StringBuffer innerhalb der Schleife zu deklarieren.
Mark Elliot
11
Ah, ich denke sb.setLength (0); ist sauberer und effizienter als das Deklarieren innerhalb der Schleife. Ihre Lösung widerspricht dem Leistungsvorteil der Verwendung von StringBuffer ...
Jon
6
Ich denke, der Leistungsvorteil liegt in der Veränderbarkeit der Zeichenfolgen und nicht in der Speicherung der Instanziierung. Hier ist ein kurzer Test von 1e8-Iterationen: Innenschleife (2.97s): ideone.com/uyyTL14w , Außenschleife (2.87s): ideone.com/F9lgsIxh
Mark Elliot
6
Apropos Leistung: Sofern in einem Multithread-Szenario nicht auf Ihren Code zugegriffen wird, sollten Sie StringBuilder anstelle von StringBuffer verwenden - siehe javadoc: "Wenn möglich, wird empfohlen, diese Klasse gegenüber StringBuffer vorzuziehen, da sie unter schneller ist die meisten Implementierungen ".
Rahel Lüthy
4
Der einzige Vorteil der Erstellung des SB außerhalb besteht darin, dass das interne (möglicherweise lange) Zeichen [] nicht verloren geht. Wenn es im ersten Iterator groß genug geworden ist, muss die zweite Schleife kein char [] ändern. Um den Vorteil zu erzielen, muss die "Clear-Methode" jedoch die Größe des internen Arrays beibehalten. setLength macht das, setzt aber auch alle nicht verwendeten Zeichen im SB auf \ u0000, so dass es weniger leistungsfähig ist, einfach einen neuen SB mit einer guten Anfangskapazität zu erstellen. Es ist besser, innerhalb der Schleife zu deklarieren.
Helios
48
Der einfachste Weg, das wiederzuverwenden, StringBufferist die Verwendung der MethodesetLength()
sb.setLength(0);// It will just discard the previous data, which will be garbage collected later.
Oder verwenden Sie:
sb.delete(0, sb.length());// A bit slower as it is used to delete sub sequence.
HINWEIS
Vermeiden Sie Deklarationen StringBufferoder StringBuilderObjekte innerhalb der Schleife, da sonst mit jeder Iteration neue Objekte erstellt werden. Das Erstellen von Objekten erfordert Systemressourcen, Speicherplatz und Zeit. Vermeiden Sie es daher auf lange Sicht, sie innerhalb einer Schleife zu deklarieren, wenn dies möglich ist.
Ich schlage vor, für jede Iteration eine neue StringBuffer(oder noch bessere StringBuilder) zu erstellen . Der Leistungsunterschied ist wirklich vernachlässigbar, aber Ihr Code wird kürzer und einfacher.
Wenn Sie Hinweise auf einen solchen Leistungsunterschied haben, teilen Sie diese bitte mit. (Ich werde auch froh sein, Statistiken darüber zu sehen, wo Java am häufigsten verwendet wird und unter welcher Definition von "meistens".)
Eli Acherkan
1
Es ist bekannt, dass die Zuordnung (neues Schlüsselwort in Java) teurer ist als nur das Ändern einiger Felder desselben Objekts. Für "meistens", mit denen Sie hochgradig replavieren können, gibt es mehr als 1,5 Milliarden Android-Geräte, die alle Java verwenden.
Louis CAD
1
Ich bin damit einverstanden, dass in einigen Fällen die Lesbarkeit des Codes wichtiger ist als die Leistung, aber in diesem Fall ist es nur eine Codezeile! Und Sie können einen Benchmark durchführen, der Ihnen beweist, dass die Zuordnung und Objekterstellung sowie das Sammeln von Müll teurer ist, als dies überhaupt nicht zu tun. Da wir uns in einer Schleife befinden, ist dies mehr als relevant.
Louis CAD
1
Ich habe auch Knuths Ansicht unterschrieben, aber seine Sichtweise ist nicht immer wahr. Das Hinzufügen von nur einer Zeile, um potenziell CPU-Zyklen und Speicher zu gewinnen, ist absolut nicht böse. Sie nehmen die Idee zu klar. Beachten Sie, dass eine Schleife normalerweise viele Male wiederholt wird. Eine Schleife kann tausende Male wiederholt werden, was auf einem Mobiltelefon (und auch auf einem Server oder Computer) wertvolle Megabyte verbrauchen kann, wenn sie nicht sorgfältig optimiert wird.
Louis CAD
1
Ich denke, wir haben beide unsere Standpunkte klar genug dargelegt, und ich bin der Meinung, dass eine weitere Diskussion für diesen Kommentarbereich nicht von Vorteil sein wird. Wenn Sie der Meinung sind, dass meine Antwort falsch, irreführend oder unvollständig ist, können Sie - oder jeder andere - sie auf jeden Fall bearbeiten und / oder ablehnen.
Schon gute Antwort da. Fügen Sie einfach ein Benchmark-Ergebnis für den Leistungsunterschied zwischen StringBuffer und StringBuild hinzu. Verwenden Sie eine neue Instanz in der Schleife oder setLength (0) in der Schleife.
Die Zusammenfassung lautet: In einer großen Schleife
StringBuilder ist viel schneller als StringBuffer
Das Erstellen einer neuen StringBuilder-Instanz in einer Schleife hat keinen Unterschied zu setLength (0). (setLength (0) hat einen sehr sehr kleinen Vorteil als das Erstellen einer neuen Instanz.)
StringBuffer ist langsamer als StringBuilder, indem eine neue Instanz in einer Schleife erstellt wird
setLength (0) von StringBuffer ist extrem langsamer als das Erstellen einer neuen Instanz in einer Schleife.
Sehr einfacher Benchmark (ich habe den Code nur manuell geändert und verschiedene Tests durchgeführt):
publicclassStringBuilderSpeed{publicstaticfinalchar ch[]=newchar[]{'a','b','c','d','e','f','g','h','i'};publicstaticvoid main(String a[]){int loopTime =99999999;long startTime =System.currentTimeMillis();StringBuilder sb =newStringBuilder();for(int i =0; i < loopTime; i++){for(char c : ch){
sb.append(c);}
sb.setLength(0);}long endTime =System.currentTimeMillis();System.out.println("Time cost: "+(endTime - startTime));}
}}
Neue StringBuilder-Instanz in Schleife: Zeitkosten: 3693, 3862, 3624, 3742
Wieder StringBuilder setLength, um sicherzustellen, dass mein Labtop kein Problem damit hat, so lange für StringBuffer setLength zu verwenden :-) Zeitkosten: 3448
Antworten:
Eine Möglichkeit besteht darin, die Löschmethode wie folgt zu verwenden:
Eine andere Option (Bit Cleaner) verwendet setLength (int len) :
Siehe Javadoc für weitere Informationen:
quelle
Der einfachste Weg, das wiederzuverwenden,
StringBuffer
ist die Verwendung der MethodesetLength()
public void setLength(int newLength)
Sie können den Fall mögen
quelle
setLength
stattsetlength
.Sie haben zwei Möglichkeiten:
Verwenden Sie entweder:
Oder verwenden Sie:
HINWEIS
Vermeiden Sie Deklarationen
StringBuffer
oderStringBuilder
Objekte innerhalb der Schleife, da sonst mit jeder Iteration neue Objekte erstellt werden. Das Erstellen von Objekten erfordert Systemressourcen, Speicherplatz und Zeit. Vermeiden Sie es daher auf lange Sicht, sie innerhalb einer Schleife zu deklarieren, wenn dies möglich ist.quelle
quelle
Ich schlage vor, für jede Iteration eine neue
StringBuffer
(oder noch bessereStringBuilder
) zu erstellen . Der Leistungsunterschied ist wirklich vernachlässigbar, aber Ihr Code wird kürzer und einfacher.quelle
Verwendung:
Aus Gründen der Lesbarkeit halte ich dies für die beste Lösung.
quelle
Schon gute Antwort da. Fügen Sie einfach ein Benchmark-Ergebnis für den Leistungsunterschied zwischen StringBuffer und StringBuild hinzu. Verwenden Sie eine neue Instanz in der Schleife oder setLength (0) in der Schleife.
Die Zusammenfassung lautet: In einer großen Schleife
Sehr einfacher Benchmark (ich habe den Code nur manuell geändert und verschiedene Tests durchgeführt):
}}
Neue StringBuilder-Instanz in Schleife: Zeitkosten: 3693, 3862, 3624, 3742
StringBuilder setLength: Zeitkosten: 3465, 3421, 3557, 3408
Neue StringBuffer-Instanz in Schleife: Zeitkosten: 8327, 8324, 8284
StringBuffer setLength Zeitkosten: 22878, 23017, 22894
Wieder StringBuilder setLength, um sicherzustellen, dass mein Labtop kein Problem damit hat, so lange für StringBuffer setLength zu verwenden :-) Zeitkosten: 3448
quelle
Ich denke, dieser Code ist schneller.
quelle