Migliori pratiche / prestazioni: mescolare StringBuilder.append con String.concat


87

Sto cercando di capire qual è la best practice e perché concatenare stringhe letterali e variabili per casi diversi. Ad esempio, se ho un codice come questo

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

È questo il modo per farlo? Da questo post , ho notato che l' +operatore su Strings crea una nuova istanza di StringBuilder, concatena gli operandi e restituisce una conversione String, che sembra molto più laboriosa della semplice chiamata .append(); quindi se è vero, allora è fuori discussione. Ma di cosa String.concat()? È corretto da utilizzare .append()per ogni concatenazione? O solo per le variabili e i valori letterali possono essere aggiunti .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

Quali sono le regole generali per le migliori pratiche e prestazioni per affrontare queste situazioni? La mia ipotesi è corretta +e non dovrebbe essere utilizzata?


Penso che fondamentalmente ce l'hai. Le opinioni divergono sul fatto che String + "in realtà non debba essere usato". Il punto è che tu capisca le conseguenze
ControlAltDel

Risposte:


185

+ operatore

String s = s1 + s2

Dietro le quinte questo si traduce in:

String s = new StringBuilder(s1).append(s2).toString();

Immagina quanto lavoro extra aggiunge se hai s1 + s2qui:

stringBuilder.append(s1 + s2)

invece di:

stringBuilder.append(s1).append(s2)

Stringhe multiple con +

Vale la pena notare che:

String s = s1 + s2 + s3 + ... +sN

è tradotto in:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

Stringcrea un char[]array che può contenere sia s1e s2. Copie s1e s2contenuti in questo nuovo array. In realtà richiede meno lavoro +dell'operatore.

StringBuilder.append()

Mantiene un char[]array interno che cresce quando necessario. Nessun extra char[]viene creato se quello interno è sufficientemente grande.

stringBuilder.append(s1.concat(s2))

ha anche prestazioni scadenti perché s1.concat(s2)crea un char[]array extra e copia s1e s2ad esso solo per copiare il nuovo contenuto dell'array all'internoStringBuilder char[] .

Detto questo, dovresti usare append()sempre e aggiungere stringhe grezze (il tuo primo frammento di codice è corretto).


Grazie per il tuo aiuto e per la spiegazione approfondita; questo è ciò di cui avevo davvero bisogno.
Nick Rolando

12
Sebbene le versioni più recenti del compilatore ottimizzino automaticamente l'operatore + per un generatore di stringhe, non è necessariamente una buona cosa presumere che lo farà come le versioni precedenti no. C'è un argomento molto importante che viene ignorato in tutta questa discussione che è in realtà uno degli scopi principali di StringBuilder che è il pool di stringhe. L'uso di un generatore di stringhe mantiene tutto come un carattere [] e non crea una stringa intermedia come faceva l'operatore + prima delle ottimizzazioni del compilatore (usato solo per eseguire un concatenamento). L'utilizzo di concat crea un oggetto String intermedio che viene memorizzato nella cache ma non utilizzato.
LINEMAN78

Quindi, se sto eseguendo una singola istruzione (non più istruzioni su un metodo) la concatenazione su diverse stringhe. Andrebbe bene usare +sugli oggetti String invece di creare una StringBuilderconcatenazione per questa volta, dal momento che fondamentalmente farà la stessa cosa?
Nick Rolando

1
E se voglio concatenare solo un carattere, è meglio usare .append ('\ n') invece di .append ("\ n")? Come un carattere è un tipo primitivo e una stringa è un oggetto?
VRWIM

3
Effective Java 2-nd edition : l' utilizzo ripetuto dell'operatore di concatenazione di stringhe per concatenare n stringhe richiede il tempo quadratico in n. Quindi è ancora rilevante?
gkiko

16

Il compilatore ottimizza la + concatenazione.

Così

int a = 1;
String s = "Hello " + a;

si trasforma in

new StringBuilder().append("Hello ").append(1).toString();

C'è un eccellente argomento qui che spiega perché dovresti usare l'operatore +.


3
Il compilatore lo ottimizzerebbe effettivamente in String s = "Hello World";quanto usi i letterali.
ColinD

@ColinD: +1. Ho appena modificato il mio snippet.

3

L'ottimizzazione viene eseguita automaticamente dal compilatore.

Il compilatore Java2 convertirà automaticamente quanto segue:

String s = s1 + s2; 

per

String s = (new StringBuffer()).append(s1).append(s2).toString();

Tratto direttamente dalle best practice Java sul sito Web di Oracles.


2

Dovresti sempre usare append.

concatcrea una nuova stringa in modo che sia abbastanza come +penso.

Se tu concato usi +con 2 stringhe finali, la JVM può fare l'ottimizzazione, quindi è come fare append in questo caso.


1

Se concatenate esattamente due stringhe usate String.concat (crea una nuova stringa creando un nuovo char-array che si adatta a entrambe le stringhe e copia i char array di entrambe le stringhe in esso).

Se concatenate più (più di due) stringhe in una riga, usate + o StringBuilder.append, non importa, poiché il compilatore converte + in StringBuilder.append. Ciò è utile per più stringhe perché mantiene un array di caratteri che cresce secondo necessità.

Se concatenate più stringhe su più righe, create uno StringBuilder e utilizzate il metodo append. Alla fine, quando hai finito di aggiungere stringhe a StringBuilder, usa il suo metodo .toString () per creare una stringa da esso. Per la concatenazione su più righe, questo è più veloce del secondo metodo, poiché il secondo metodo creerebbe un nuovo StringBuilder su ogni riga, aggiungerà le stringhe e quindi eseguirà il cast su String, mentre il terzo metodo utilizza solo uno StringBuilder per l'intera operazione.


0

Utilizzare l' +operatore è la migliore pratica, è anche semplice e leggibile.

Il linguaggio Java fornisce un supporto speciale per l'operatore di concatenazione di stringhe (+) e per la conversione di altri oggetti in stringhe. La concatenazione di stringhe viene implementata tramite la classe StringBuilder (o StringBuffer) e il relativo metodo append.

Documento ufficiale: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html


0

a livello di codice byte non c'è differenza e non stiamo compromettendo l'efficacia. In caso di esecuzione a livello di codice byte, deve passare attraverso il metodo di sovraccarico dell'operatore non inline per + chiamando append. quindi a livello di linguaggio assembly (Java è scritto in C e C produce assembly simili all'assembly, ci sarà una chiamata di registro extra per memorizzare + la chiamata al metodo nello stack e ci sarà un push aggiuntivo (in realtà, il cross-compilatore potrebbe ottimizzare + l'operatore chiamata, in tal caso non fa differenza con l'efficacia.)

È buona norma disporre di un modo per aumentare la leggibilità. :)


0

Personalmente preferisco il formattatore di stringhe diStrings.format() una riga semplice e facile da leggere .

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F

0

Tutte le risposte sono abbastanza buone e esplicative. Ma ho sentito che anche l'esplorazione di altre tecniche di concatenazione di stringhe sarebbe stata d'aiuto come: Guava Joiner, Streams, String.format ecc.

Per dettagli completi sulle prestazioni di ciascuna tecnica di concatenazione java-string-concatenation-which-way-is-best .

In breve, le prestazioni di concatenazione variano con n. di stringhe da concatenare. Ad esempio, per concatenare 1-10 stringhe, queste tecniche funzionano meglio: StringBuilder, StringBuffer e Plus Operator. E per concatenare centinaia di stringhe - Guava Joiner, anche la libreria stringsUtils di Apache funziona alla grande.

Si prega di passare attraverso il blog sopra. Spiega davvero molto bene l'efficienza delle prestazioni.

Grazie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.