2010-07-19 19 views
5

Ich lese viel über die Verwendung von StringBuffer und String vor allem, wo die Verkettung in Java betroffen ist und ob man threadsicher ist oder nicht.Verwenden von String oder StringBuffer in Java: Was ist besser?

Also, in verschiedenen Java-Methoden, die verwendet werden sollten?

Zum Beispiel in einem PreparedStatement sollte Abfrage ein String sein:

String query = ("SELECT * " + 
        "FROM User " + 
        "WHERE userName = ?;"); 

    try { 
     ps = connection.prepareStatement(query); 

Und dann wieder, in einer String Utility-Methoden wie:

public static String prefixApostrophesWithBackslash(String stringIn) { 
    String stringOut = stringIn.replaceAll("'", "\\\\'"); 
    return stringOut; 
} 

Und:

// Removes a char from a String. 
public static String removeChar(String stringIn, char c) { 
    String stringOut = (""); 
    for (int i = 0; i < stringIn.length(); i++) { 
     if (stringIn.charAt(i) != c) { 
      stringOut += stringIn.charAt(i); 
     } 
    } 
    return stringOut; 
} 

Sollte ich StringBuffers verwenden? Vor allem, wo repalceAll für solche Objekte sowieso nicht verfügbar ist.

Danke

Herr Morgan.

Danke für den ganzen Rat. StringBuffers wurden durch StringBuilders ersetzt und Strings durch StringBuilders ersetzt, wo ich es für die beste hielt.

Antwort

7

Sie müssen fast nie StringBuffer verwenden.

Anstelle von StringBuffer meinen Sie wahrscheinlich StringBuilder. Ein StringBuffer ist wie ein StringBuilder, außer dass er auch Thread-Sicherheit bietet. Diese Thread-Sicherheit wird in der Praxis selten benötigt und führt nur dazu, dass der Code langsamer ausgeführt wird.

Ihre Frage scheint nicht über String vs StringBuffer, sondern über die Verwendung von integrierten Methoden oder die Implementierung des Codes selbst zu sein. Wenn es eine integrierte Methode gibt, die genau das tut, was Sie wollen, sollten Sie es wahrscheinlich verwenden. Die Wahrscheinlichkeit ist viel besser als der Code, den Sie schreiben würden.

+1

Ich würde hoffen, dass im ersten Beispiel kein StringBuilder intern verwendet wird, stattdessen kann der Compiler die Strings nur zu einer Zeichenfolge verketten, da es keine Variabilität gibt. –

+0

Das ist ein sehr guter Punkt ... entfernt das bisschen. –

+0

Aber da diese PreparedStatement in einem Multi-Thread-Szenario verwendet werden könnte, wäre StringBuffer nicht besser? –

1

Für den unten Codesegment

// Removes a char from a String. 
public static String removeChar(String stringIn, char c) { 
    String stringOut = (""); 
    for (int i = 0; i < stringIn.length(); i++) { 
     if (stringIn.charAt(i) != c) { 
      stringOut += stringIn.charAt(i); 
     } 
    } 
    return stringOut; 
} 

Sie tun könnten, nur stringIn.replaceAll(c+"","")

0

Für Fälle, die Single-Threaded in Betracht gezogen werden können, wäre die beste StringBuilder sein. Es fügt keinen Synchronisierungsaufwand hinzu, während StringBuffer dies tut. Die Stringverkettung mit dem Operator '+' ist nur dann "gut", wenn Sie StringBuilder verwenden oder einfach den Code gut lesbar halten möchten. Dies ist unter dem Gesichtspunkt der Leistung akzeptabel, wie in der Logmeldung "LOG" .info ("Starting instance" + inst_id + "of" + app_name); "

+0

Tatsächlich wird in der überwiegenden Mehrheit der Fälle der Compiler die zweite Form in eine Sequenz von StringBuilder-Aufrufen verwandeln. In der Regel ist es besser, die String-Verkettung für die Art von Dingen zu verwenden, die Sie in Ihrem Beispiel angegeben haben, da es sauberer ist. Sie würden StringBuilder für alles verwenden, was Sie nicht direkt miteinander verketten. z.B. in einer Schleife oder wenn Sie den Builder zwischen Funktionsaufrufen übergeben. –

+0

@Andrzej Doyle - Eigentlich habe ich vorgeschlagen, String-Verkettung in meinem Beispiel zu verwenden. Bitte lesen Sie sorgfältig, bevor Sie kommentieren. – bobah

+0

Ja, aber der zweite Absatz impliziert, dass die Leistung schlechter ist. Mein Punkt war, dass der Compiler in den meisten Fällen (bei denen die Verknüpfungsoperation lexikalisch statisch ist) ihn trotzdem in einen StringBuilder-äquivalenten Bytecode * verwandelt *.Also, du bekommst deinen Kuchen und isst ihn, was nicht der Eindruck ist, den ich gespürt habe. –

1

Selbst im MT-Code ist es ungewöhnlich, dass mehrere Threads Material an eine Zeichenfolge anhängen. StringBuilder wird fast immer StringBuffer vorgezogen.

3

Es gibt keine einfache Antwort (abgesehen von der Wiederholung des Mantras StringBuilder gegenüber StringBuffer ...). Sie haben wirklich verstanden, was "unter der Haube" passiert, um die effizienteste Lösung zu finden. In Ihrem ersten Beispiel ist String der Weg zu gehen.Der Java-Compiler kann ziemlich optimalen Code (unter Verwendung eines StringBuilder falls notwendig) für jeden Ausdruck erzeugen, der aus einer Folge von String-Verkettungen besteht. Und wenn die verketteten Zeichenfolgen alle Konstanten oder Literale sind, kann der Compiler tatsächlich die Verkettung zur Kompilierungszeit durchführen.

In Ihrem zweiten Beispiel ist nicht ganz klar, ob String oder StringBuilder wäre besser ... oder ob sie in etwa gleichwertig wären. Man müsste sich den Code der java.util.regex.Matcher Klasse anschauen, um das herauszufinden.

BEARBEITEN - Ich schaute auf den Code, und tatsächlich macht es keinen großen Unterschied, ob Sie einen String oder StringBuilder als Quelle verwenden. Intern erstellt die Methode Matcher.replaceAll einen neuen StringBuilder und füllt ihn, indem er Chunks aus der Quellzeichenfolge und der Ersetzungszeichenfolge anfügt. In Ihrem dritten Beispiel wäre ein StringBuilder eindeutig am besten. Ein Java-Compiler der aktuellen Generation kann den Code (wie beschrieben) nicht optimieren, um zu vermeiden, dass beim Hinzufügen jedes Zeichens ein neuer String erstellt wird.

1

Moderne Compiler optimieren den Code bereits. Daher werden einige String-Zusätze für die Verwendung von StringBuilder optimiert, und wir können die String-Additionen beibehalten, wenn wir denken, dass dies die Lesbarkeit erhöht.

Beispiel 1:

StringBuiler sb = new StringBuilder(); 
sb.append("SELECT * "); 
sb.append("FROM User "); 
sb.append("WHERE userName = ?;"); 
String query = sb.toString(); 

Beispiel 2:

String numbers = ""; 
for (int i = 0;i < 20; i++) 
    numbers = numbers + i; 

Dies optimiert und wir können nicht

String query = ("SELECT * " + 
       "FROM User " + 
       "WHERE userName = ?;"); 

wird auf ungefähr wie optimiert werden sollte einen Strin verwenden gBuilder im Code.


Ich machte diese Beobachtung für SUN jdk1.5 +. Für ältere Java-Versionen oder andere jdks kann es also anders sein. Dort könnte es sein, immer StringBuilder (oder StringBuffer für jdk 1.4.2 und älter) zu codieren.

+2

Eigentlich, wenn Sie String-Konstanten verketten, wird der Compiler es in eine einzige String-Konstante optimieren. – ILMTitan

Verwandte Themen