Antworten:
Mutabilitätsunterschied:
String
ist unveränderlich , wenn Sie versuchen , ihre Werte zu ändern, wird eine andere Aufgabe erstellt, während StringBuffer
und StringBuilder
sind wandelbar , so können sie ihre Werte ändern.
Thread-Sicherheitsunterschied:
Der Unterschied zwischen StringBuffer
und StringBuilder
ist, dass StringBuffer
es threadsicher ist. Wenn die Anwendung nur in einem einzigen Thread ausgeführt werden muss, ist es besser, sie zu verwenden StringBuilder
. StringBuilder
ist effizienter als StringBuffer
.
Situationen:
String
Objekt unveränderlich ist.StringBuilder
ausreichend.StringBuffer
da StringBuffer
es synchron ist, damit Sie Thread-Sicherheit haben.Strings
wenn wir den Wert ein anderes Objekt verändern wird erstellt. Wird die alte Objektreferenz ungültig gemacht, so dass es sich um Müll handelt, der von der gesammelt wurde, GC
oder wird sie sogar durch Müll gesammelt?
String
with anwenden StringBuilder
?
String
wenn eine unveränderliche Struktur angemessen ist. Das Abrufen einer neuen Zeichenfolge von a String
kann zu einer inakzeptablen Leistungseinbußen führen, entweder in Bezug auf die CPU-Zeit oder den Arbeitsspeicher (das Abrufen von Teilzeichenfolgen ist CPU-effizient, da die Daten nicht kopiert werden, dies bedeutet jedoch, dass möglicherweise eine viel größere Datenmenge zugewiesen bleibt).StringBuilder
Option, wenn Sie eine veränderbare Zeichenfolge erstellen müssen, um normalerweise mehrere Zeichenfolgen miteinander zu verknüpfen.StringBuffer
unter den gleichen Umständen, die Sie verwenden würden StringBuilder
, aber wenn Änderungen an der zugrunde liegenden Zeichenfolge synchronisiert werden müssen (da mehrere Threads den Zeichenfolgenpuffer lesen / ändern).Sehen Sie ein Beispiel hier .
Die Grundlagen:
String
ist eine unveränderliche Klasse, sie kann nicht geändert werden.
StringBuilder
ist eine veränderbare Klasse, an die Zeichen angehängt, ersetzt oder entfernt und schließlich in eine konvertierte String
StringBuffer
ursprüngliche Version von konvertiert werden könnenStringBuilder
Sie sollten es StringBuilder
in allen Fällen vorziehen, in denen nur ein einziger Thread auf Ihr Objekt zugreift.
Die Details:
Beachten Sie auch, dass dies StringBuilder/Buffers
keine Zauberei ist, sondern lediglich ein Array als Hintergrundobjekt verwendet und dass das Array neu zugewiesen werden muss, wenn es voll wird. Stellen Sie sicher, dass Ihre StringBuilder/Buffer
Objekte ursprünglich groß genug sind, damit sie nicht jedes Mal, wenn sie .append()
aufgerufen werden, ständig in der Größe geändert werden müssen.
Die Größenänderung kann sehr degeneriert werden. Grundsätzlich wird die Größe des Backing-Arrays bei jeder Erweiterung auf das Zweifache seiner aktuellen Größe geändert. Dies kann dazu führen, dass große Mengen an RAM zugewiesen und nicht verwendet werden, wenn StringBuilder/Buffer
Klassen größer werden.
In Java String x = "A" + "B";
verwendet man einen StringBuilder
Blick hinter die Kulissen. In einfachen Fällen gibt es also keinen Vorteil, wenn Sie Ihre eigenen deklarieren. Wenn Sie jedoch Objekte String
erstellen, die groß sind, z. B. weniger als 4 KB, ist das Deklarieren StringBuilder sb = StringBuilder(4096);
viel effizienter als die Verkettung oder die Verwendung des Standardkonstruktors mit nur 16 Zeichen. Wenn Ihr String
Wert unter 10.000 liegt, initialisieren Sie ihn aus Sicherheitsgründen mit dem Konstruktor auf 10.000. Wenn es jedoch auf 10k initialisiert ist, schreiben Sie 1 Zeichen mehr als 10k, wird es neu zugewiesen und in ein 20k-Array kopiert. Hoch zu initialisieren ist also besser als zu niedrig.
Im Fall der automatischen Größenänderung wird das Hintergrundarray beim 17. Zeichen neu zugewiesen und auf 32 Zeichen kopiert. Beim 33. Zeichen geschieht dies erneut, und Sie können das Array neu zuweisen und in 64 Zeichen kopieren. Sie können sehen, wie dies zu vielen Neuzuweisungen und Kopien führt, was Sie wirklich zu vermeiden versuchen StringBuilder/Buffer
.
Dies ist aus dem JDK 6-Quellcode für AbstractStringBuilder
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
Eine bewährte Methode besteht darin, das StringBuilder/Buffer
etwas größere zu initialisieren, als Sie denken, dass Sie es benötigen werden, wenn Sie nicht String
sofort wissen, wie groß das sein wird, aber Sie können raten. Eine Zuweisung von etwas mehr Speicher als Sie benötigen, ist besser als viele Neuzuweisungen und Kopien.
Achten Sie auch darauf, a StringBuilder/Buffer
mit a zu initialisieren String
, da dies nur die Größe des Strings + 16 Zeichen zuweist. In den meisten Fällen wird nur die entartete Neuzuweisung und der Kopierzyklus gestartet, die Sie vermeiden möchten. Das Folgende stammt direkt aus dem Java 6-Quellcode.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Wenn Sie zufällig eine Instanz haben StringBuilder/Buffer
, die Sie nicht erstellt haben und den aufgerufenen Konstruktor nicht steuern können, können Sie das entartete Verhalten beim erneuten Zuweisen und Kopieren vermeiden. Rufen Sie .ensureCapacity()
mit der gewünschten Größe an, um sicherzustellen, dass das Ergebnis String
passt.
Die Alternativen:
Nur als Anmerkung, wenn Sie wirklich tun schwere String
Gebäude und Manipulation, gibt es eine viel leistungsorientierte Alternative genannt Seile .
Eine andere Alternative besteht darin, eine StringList
Implementierung durch Unterklassifizierung zu erstellen ArrayList<String>
und Zähler hinzuzufügen, um die Anzahl der Zeichen bei jeder .append()
und anderen Mutationsoperationen der Liste zu verfolgen. Anschließend werden sie überschrieben .toString()
, um eine StringBuilder
der genau benötigten Größen zu erstellen und die Liste zu durchlaufen und zu erstellen Bei der Ausgabe können Sie sogar StringBuilder
eine Instanzvariable erstellen und die Ergebnisse von "zwischenspeichern" .toString()
und müssen sie nur neu generieren, wenn sich etwas ändert.
Vergessen Sie auch nicht, String.format()
wenn Sie eine fest formatierte Ausgabe erstellen, die vom Compiler optimiert werden kann, wenn sie besser wird.
String x = "A" + "B";
kompilieren wirklich ein String zu sein? Warum sollte es nicht einfach kompiliert werden String x = "AB";
, es sollte nur einen StringBuilder verwenden, wenn die Komponenten zur Kompilierungszeit nicht bekannt sind.
Meinen Sie zur Verkettung?
Beispiel aus der realen Welt: Sie möchten aus vielen anderen eine neue Zeichenfolge erstellen .
Zum Beispiel, um eine Nachricht zu senden:
String
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
StringBuilder
String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" )
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm " ).append( user.age ).append( "yrs. old too")
.toString()
Oder
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (die Syntax ist genau wie bei StringBuilder, die Effekte unterscheiden sich)
Über
StringBuffer
vs. StringBuilder
Ersteres ist synchronisiert und später nicht.
Wenn Sie es also mehrmals in einem einzelnen Thread aufrufen (was 90% der Fälle entspricht), StringBuilder
wird es viel schneller ausgeführt, da es nicht aufhört zu sehen, ob es die Thread-Sperre besitzt.
Daher ist die Verwendung empfehlenswert StringBuilder
(es sei denn, Sie haben natürlich mehr als einen Thread gleichzeitig, der darauf zugreift, was selten vorkommt).
String
Die Verkettung ( mit dem Operator + ) kann vom Compiler so optimiert werden StringBuilder
, dass sie darunter verwendet wird. In den älteren Tagen von Java war dies also kein Grund mehr, sich Sorgen zu machen. Dies war etwas, von dem jeder sagt, dass es um jeden Preis vermieden werden sollte, da jede Verkettung hat ein neues String-Objekt erstellt. Moderne Compiler tun dies nicht mehr, aber es ist dennoch eine gute Praxis, sie StringBuilder
stattdessen zu verwenden, nur für den Fall, dass Sie einen "alten" Compiler verwenden.
bearbeiten
Nur für diejenigen, die neugierig sind, macht der Compiler Folgendes für diese Klasse:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
javap -c StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldc #4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldc #4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
Die Zeilen mit den Nummern 5 bis 27 stehen für die Zeichenfolge mit dem Namen "Literal".
Die Zeilen mit den Nummern 31-53 stehen für den String "builder".
Es ist kein Unterschied, für beide Zeichenfolgen wird genau der gleiche Code ausgeführt.
StringBuilder
String-Verkettung auf der rechten Seite der Zuweisung zu verwenden. Jede gute Implementierung verwendet einen StringBuilder hinter den Kulissen, wie Sie sagen. Darüber hinaus "a" + "b"
würde Ihr Beispiel von in ein einziges Literal kompiliert, "ab"
aber wenn Sie es verwenden StringBuilder
, würde es zu zwei unnötigen Aufrufen von führen append()
.
"a"+"b"
sondern sagen, was eine String-Verkettung war. Ich ändere sie so, dass sie explizit ist. Was Sie nicht sagen, ist, warum es keine gute Praxis ist, dies zu tun. Genau das macht (ein moderner) Compiler. @fuzzy, ich stimme zu, besonders wenn Sie wissen, wie groß die endgültige Zeichenfolge sein würde (ca.).
-------------------------------------------------- -------------------------------- String StringBuffer StringBuilder -------------------------------------------------- -------------------------------- Lagerbereich | Constant String Pool Heap Heap Änderbar | Nein (unveränderlich) Ja (veränderlich) Ja (veränderlich) Thread Safe | Ja, ja, nein Leistung | Schnell Sehr langsam Schnell -------------------------------------------------- --------------------------------
synchronised
und das ist der Grund .
String
Das String class
steht für Zeichenketten. Alle Zeichenfolgenliterale in Java-Programmen, wie "abc"
sie als Instanzen dieser Klasse implementiert sind.
String-Objekte sind nach ihrer Erstellung unveränderlich. Wir können sie nicht ändern. ( Strings sind Konstanten )
Wenn ein String verwendet Konstruktor oder eine Methode erstellt , dann werden diese Strings in gespeichert werden Heap - Speicher sowie SringConstantPool
. Vor dem Speichern im Pool wird jedoch die intern()
Methode aufgerufen , um die Objektverfügbarkeit mit demselben Inhalt im Pool mithilfe der Methode equals zu überprüfen. Wenn String-copy im Pool verfügbar ist, wird die Referenz zurückgegeben. Andernfalls wird das String-Objekt zum Pool hinzugefügt und gibt die Referenz zurück.
+
) und für die Konvertierung anderer Objekte in Strings. Die Verkettung von Zeichenfolgen wird über die Klasse StringBuilder (oder StringBuffer) und ihre Append-Methode implementiert.String heapSCP = new String("Yash");
heapSCP.concat(".");
heapSCP = heapSCP + "M";
heapSCP = heapSCP + 777;
// For Example: String Source Code
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
String-Literale werden in gespeichert StringConstantPool
.
String onlyPool = "Yash";
StringBuilder und StringBuffer sind veränderbare Zeichenfolgen. Das heißt, man kann den Wert dieser Objekte ändern. StringBuffer hat die gleichen Methoden wie der StringBuilder, aber jede Methode in StringBuffer ist synchronisiert, sodass sie threadsicher ist.
StringBuffer- und StringBuilder-Daten können nur mit einem neuen Operator erstellt werden. Sie werden also im Heap-Speicher gespeichert.
Instanzen von StringBuilder können nicht von mehreren Threads verwendet werden. Wenn eine solche Synchronisation erforderlich ist, wird empfohlen, StringBuffer zu verwenden.
StringBuffer threadSafe = new StringBuffer("Yash");
threadSafe.append(".M");
threadSafe.toString();
StringBuilder nonSync = new StringBuilder("Yash");
nonSync.append(".M");
nonSync.toString();
StringBuffer und StringBuilder haben spezielle Methoden wie.,
replace(int start, int end, String str)
Und reverse()
.
HINWEIS : StringBuffer und SringBuilder können geändert werden, da sie die Implementierung von bereitstellen
Appendable Interface
.
Wann welches zu verwenden ist.
Wenn Sie den Wert nicht jedes Mal ändern möchten, ist es besser, ihn zu verwenden String Class
. Wenn Sie als Teil von Generics Comparable<T>
Werte sortieren oder vergleichen möchten, wählen Sie String Class
.
//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable
Set<StringBuffer> set = new TreeSet<StringBuffer>();
set.add( threadSafe );
System.out.println("Set : "+ set);
Wenn Sie den Wert jedes Mal ändern möchten, wählen Sie StringBuilder, der schneller als StringBuffer ist. Wenn mehrere Threads den Wert ändern, wählen Sie StringBuffer.
Auch StringBuffer
ist threadsicher, was StringBuilder
nicht ist.
In einer Echtzeitsituation, in der verschiedene Threads darauf zugreifen, StringBuilder
kann dies zu einem unbestimmten Ergebnis führen.
Beachten Sie, dass Sie StringBuilder
anstelle von Java 5 oder neuer anstelle von verwenden sollten StringBuffer
. Aus der API-Dokumentation:
Ab Release JDK 5 wurde diese Klasse durch eine entsprechende Klasse ergänzt, die für die Verwendung durch einen einzelnen Thread entwickelt wurde
StringBuilder
. DieStringBuilder
Klasse sollte im Allgemeinen dieser vorgezogen werden, da sie alle gleichen Operationen unterstützt, jedoch schneller ist, da keine Synchronisation durchgeführt wird.
In der Praxis werden Sie dies fast nie von mehreren Threads gleichzeitig verwenden, sodass die Synchronisierung StringBuffer
fast immer unnötigen Aufwand bedeutet.
Persönlich glaube ich nicht, dass es eine reale Verwendung für gibt StringBuffer
. Wann würde ich jemals zwischen mehreren Threads kommunizieren wollen, indem ich eine Zeichenfolge manipuliere? Das klingt überhaupt nicht nützlich, aber vielleicht muss ich das Licht noch sehen :)
Der Unterschied zwischen String und den beiden anderen Klassen besteht darin, dass String unveränderlich ist und die anderen beiden Klassen veränderbare Klassen sind.
Aber warum haben wir zwei Klassen für den gleichen Zweck?
Grund dafür ist, dass StringBuffer
Thread-sicher ist und StringBuilder
nicht.
StringBuilder
ist eine neue Klasse StringBuffer Api
und wurde in eingeführt JDK5
und wird immer empfohlen, wenn Sie in einer Single-Thread-Umgebung arbeiten, da es viel istFaster
Ausführliche Informationen finden Sie unter http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
In Java ist String unveränderlich. Unveränderlich zu sein bedeutet, dass wir nach dem Erstellen eines Strings seinen Wert nicht mehr ändern können. StringBuffer ist veränderbar. Sobald ein StringBuffer-Objekt erstellt wurde, hängen wir den Inhalt einfach an den Wert des Objekts an, anstatt ein neues Objekt zu erstellen. StringBuilder ähnelt StringBuffer, ist jedoch nicht threadsicher. Die Methoden von StingBuilder sind nicht synchronisiert, aber im Vergleich zu anderen Strings läuft der Stringbuilder am schnellsten. Sie können den Unterschied zwischen String, StringBuilder und StringBuffer lernen , indem Sie sie implementieren.