2009-12-03 23 views
16

Io di solito creare una stringa in Java seguente modo:Esiste un "modo più rapido" per costruire stringhe in Java?

String foo = "123456";

Tuttavia, il mio docente ha insistito a me che la formazione di una stringa utilizzando il metodo format, come così:

String foo = String.format("%s", 123456);

è molto più veloce .

Inoltre, dice che l'uso della classe StringBuilder è ancora più veloce.

 
StringBuilder sb = new StringBuilder(); 
String foo = sb.append(String.format("%s", 123456)).toString(); 



Qual è il metodo più veloce per creare una stringa, se c'è anche una?

Non potevano essere accurati al 100% in quanto potrei non ricordarli completamente.

+0

Buona domanda, è questo autoboxing? So che Integer foo = 1 è più lento di Integer foo = Integer.valueOf (1); – Trick

+7

Essendo uno studente, sarebbe bello se riuscissi a pensare a un modo per mettere alla prova la sua teoria. Puoi scrivere una classe Java che costruisca 100000 stringhe/stringhe di stringhe e così via? –

+13

Direi al tuo professore che nel mondo reale il vantaggio di prestazione molto molto piccolo è superato di gran lunga dalla leggibilità. Inoltre, il codice dovrebbe sempre essere scritto per funzionare prima, nel modo più semplice e semplice possibile, e poi ottimizzato SE c'è un bisogno (che di solito non c'è). –

risposta

24

Se v'è una sola stringa di allora:

String foo = "123456"; 

è il più veloce. Noterai che la riga String.format ha dichiarato "%s%", quindi non vedo come il docente potrebbe pensare che sia più veloce. Inoltre, hai ricevuto una chiamata al metodo.

Tuttavia, se si sta costruendo una stringa nel tempo, ad esempio in un ciclo for, si vorrà utilizzare un oggetto StringBuilder. Se si dovesse usare solo +=, si sta creando una nuova stringa ogni volta che viene chiamata la riga+=. StringBuilder è molto più veloce poiché contiene un buffer e lo aggiunge ogni volta che chiami append.

+0

i miei pensieri esattamente. – pstanton

+1

Sì, se stai dichiarando una stringa letterale, quindi semplicemente incorporarla è ovviamente il modo più veloce. Ho avuto un prof di linguaggio di programmazione una volta ho detto alla classe che Java non aveva i puntatori, quindi non si potevano creare cose come le liste collegate, pensava che tutte le raccolte java fossero implementate in C o qualcosa del genere. Ho avuto un altro docente che diceva che i siti web "sicuri" erano quelli che terminavano in ".shtml" (piuttosto che iniziando con https) A volte semplicemente non sanno di cosa stanno parlando. –

+2

Inoltre, in un ciclo stretto potresti creare un Numero enorme di stringhe ciascuna leggermente più grande della precedente. Questo è vero anche in C# (bene .Net). Sono anche d'accordo con il commento di Eric Wendelin che dovresti scrivere un test per vedere. Non dire al tuo prof l'opinione delle persone dell'interwebz quando potresti mostrargli prove documentate del fatto che abbia ragione o torto. Farei un certo numero di casi di test: velocità per creare una stringa tramite ciascun metodo, velocità per creare lotti in un ciclo, ecc. – jeffa00

8
String foo = "some string literal"; 

è certamente il modo più veloce per fare una stringa. È incorporato nel file .class ed è una semplice ricerca di memoria da recuperare.

L'utilizzo di String.format quando non si dispone di nulla per la formattazione effettiva sembra solo brutto e potrebbe far piangere gli sviluppatori junior.

Se la stringa sta per essere modificata, quindi StringBuilder è la migliore dal Strings sono immutable.

+14

L'uso di String.format quando non si dispone di nulla per la formattazione effettiva potrebbe anche far piangere anche gli sviluppatori senior. – JasCav

4

Se la stringa è nota in fase di compilazione, è consigliabile utilizzare un valore letterale: String foo = "123456";.

Se la stringa non è nota in fase di compilazione ed è composta da un'aggregazione di stringhe più piccole, StringBuilder è in genere la strada da percorrere (ma attenzione alla sicurezza dei thread!).

Utilizzando String foo = String.format("%s", 123456);potrebbe ridurre le dimensioni tuoi .class' e rendere classe di carico è un piccolo po 'più veloce, ma sarebbe estremamente aggressivo tuning (estrema) di memoria c'è ^^.

4

Nel tuo secondo esempio, utilizzando:

String foo = String.format("%s", 123456); 

non ti comprare nulla; 123456 è già un valore costante, quindi perché non assegnare semplicemente foo = "123456"?Per stringhe costanti, non c'è modo migliore.

Se si sta creando una stringa da più parti collegate in runtime, utilizzare StringBuffer o StringBuilder (il primo è thread-safe).

3

Come è stato sottolineato, se si sta solo creando una singola stringa senza concatenazione, basta usare String.

Per concatenare più bit in una stringa grande, StringBuffer è più lento di StringBuilder, ma StringBuffer è sincronizzato. Se non hai bisogno di sincronizzazione, StringBuilder.

11

Tutta questa discussione è discutibile. Si prega di leggere questo articolo di Jeff, cioè il ragazzo che ha creato Stack Overflow.

The Sad Tragedy of Micro-Optimization Theater

prega di fare riferimento al vostro istruttore a questo post e chiedergli di smettere di rovinare il suo cervello/il suo studente con informazioni inutili. Le ottimizzazioni algoritmiche sono dove il tuo codice vivrà o morirà, non con il metodo che usi per costruire le stringhe. In ogni caso, StringBuilder e String formattatore devono eseguire ACTUAL CODE con REAL MEMORY, se si costruisce una stringa che viene messa da parte durante il tempo di compilazione ed è pronta per essere utilizzata quando ne hai bisogno, in pratica ha 0 run- costo in termini di tempo, mentre le altre opzioni hanno un costo reale, dal momento che il codice deve essere effettivamente eseguito.

+1

Non essere troppo pignolo, ma penso che tu intenda dire che la discussione è "discutibile". Anche se è "muto" anche perché SO non ha suoni ...;) – jasonh

+2

Facciamo micro-ottimizzare questo post! :) – Tim

+0

Grazie per la correzione dell'errore di ortografia. – Michael

1

Il primo esempio che hai dato è il più veloce e il più semplice. Usalo.

Ogni pezzo di codice aggiunto in questi esempi lo rende molto più lento e difficile da leggere.

vorrei suggerire esempio 2 è almeno 10-100x più lento di esempio 1 ed esempio 3 è di circa 2 volte più lento di esempio 2.

Ha fatto il processore fornisce alcuna giustificazione per questa affermazione?

BTW: Il tuo primo esempio non costruisce affatto una stringa (che è il motivo per cui è più veloce), ti dà semplicemente una stringa seduta nel pool di costanti stringa.

2

Sei sicuro al 100% che l'istruttore non stava parlando di qualcosa di simile a:

String foo = "" + 123456; 

vedo i miei studenti fare quel tipo di cosa "tutto il tempo" (una manciata farà che ogni termine). Il motivo per cui lo fanno è che alcuni libri hanno mostrato loro come farlo in quel modo. Scuote la testa e pugno agli scrittori di libri pigri!

+0

Ho pensato che fosse una scorciatoia idiomatica per 'foo = String.valueOf (int_var)'. Immagino ci sia un po 'di overhead per la creazione (riferimento a) stringa vuota, ma oltre a questo, cosa c'è di sbagliato in esso? –

+0

Non è la cosa più chiara da fare. Anche String.valueOf (int) chiama Integer.toString (int) (non è un requisito, ma è ciò che fa il JDK). Se il compilatore lo fa, sarà più lento, a seconda dell'ambiente, che chiamare Integer.toString (int). Integer.toString (int) è più chiaro, per me, di "" + int e più ovvio. – TofuBeer

14

Leggermente off-topic, ma vorrei che l'intero mito "must-not-use-plus-to-concatenate-stringhe-in-Java" andasse via. Anche se nelle prime versioni di Java era possibile che StringBuffer fosse più veloce e "+ fosse malvagio", non è certamente vero nelle moderne JVM che si prendono cura di molte ottimizzazioni.

Ad esempio, quale è più veloce?

String s = "abc" + "def"; 

o

StringBuffer buf = new StringBuffer(); 
    buf.append("abc"); 
    buf.append("def"); 
    String s = buf.toString(); 

La risposta è l'ex. La JVM riconosce che questa è una costante di stringa e che in realtà inserirà "abcdef" nel pool di stringhe, mentre la versione "ottimizzata di stringbuffer" causerà la creazione di un oggetto StringBuffer aggiuntivo.

Un'altra ottimizzazione JVM è

String s = onestring + " concat " + anotherstring; 

Dove la JVM sarà capire cosa sarà il modo migliore di concatenamento. In JDK 5, questo significa che uno StringBuilder verrà utilizzato internamente e sarà più veloce dell'utilizzo di un buffer di stringa.

Ma, come altre risposte hanno detto, il "123456" costante nella tua domanda è certamente il modo più veloce e la vostra docente dovrebbe tornare ad essere uno studente :-)

E sì, sono stato abbastanza triste per verificare questo guardando il bytecode Java ...

+0

Più Gyaan al tuo commento "Leggermente fuori tema". In un altro scenario, la creazione di stringhe con StringBuilder sarebbe più efficiente. Se si concatenano stringhe diverse tramite loop for, che in genere è il tipo String simple = ""; for (contatore int = 0, contatore <100000; contatore ++) { semplice + = contatore; } // Questa semplice operazione ha richiesto circa 12 secondi. StringBuffer buffer = new StringBuffer(); for (contatore int = 0, contatore <100000; contatore ++) { buffer.append (buffer); } // Ciò ha richiesto solo 14 ms! – mac

+0

Oops, ho appena realizzato che sto sottolineando la risposta part2 o jasonh. – mac

Problemi correlati