2011-10-15 5 views
9

Sto scrivendo un MUD (gioco basato su testo) al momento utilizzando java. Uno degli aspetti principali di un MUD è la formattazione delle stringhe e il loro invio all'utente. Come sarebbe meglio questo risultato?Java concatena per creare stringa o formato

detto che volevo inviare la seguente stringa: "Ciao"

dici a qualcuno - dove "Someone", "say" e "Hello!" sono tutte variabili. Quale sarebbe la migliore prestazione saggia?

"You " + verb + " to " + user + " \"" + text + "\""

o

String.format("You %1$s to %2$s \"%3$s\"", verb, user, text)

o qualche altra opzione?

Non sono sicuro di quale sarà più facile da usare alla fine (che è importante perché sarà ovunque), ma ci sto pensando a questo punto perché concatenare con + sta diventando un po 'di confusione con alcune delle linee più grandi. Ritengo che l'uso di StringBuilder in questo caso lo renderà ancora meno leggibile.

Qualche suggerimento qui?

+7

Non preoccuparti delle prestazioni a meno che non trovi che si tratta di un problema e che questo è il collo di bottiglia. Fai quello che pensi porterà al codice più leggibile e manutenibile. –

risposta

17

Se le stringhe vengono create utilizzando una singola espressione di concatenazione; per esempio.

String s = "You " + verb + " to " + user + " \"" + text + "\""; 

allora questo è più o meno equivalente a quello più lungo senza fiato:

StringBuilder sb = new StringBuilder(); 
sb.append("You"); 
sb.append(verb); 
sb.append(" to "); 
sb.append(user); 
sb.append(" \""); 
sb.append(text); 
sb.append('"'); 
String s = sb.toString(); 

(In realtà, il compilatore Java compilare il prima nella seconda ... quasi.)

I problemi di efficienza si presentano quando si inizia a creare stringhe intermedie o si creano stringhe usando += e così via. A quel punto, StringBuilder diventa più efficiente perché riduci il numero di stringhe intermedie che vengono create e quindi eliminate.

Ora quando si utilizza String.format(), deve essere utilizzato un StringBuilder sotto il cofano. Tuttavia, format deve anche analizzare il formato String ogni volta che si effettua la chiamata, e questo è un sovraccarico che non si ha se si costruisce la stringa in modo ottimale.


Detto questo, il mio consiglio sarebbe quello di scrivere il codice in modo che è più leggibile. Solo preoccuparsi del modo più efficiente per creare stringhe se il profilo indica che si tratta di un problema di prestazioni reali. (In questo momento, stai trascorrendo del tempo a pensare a modi per affrontare un problema di prestazioni che potrebbe rivelarsi insignificante o irrilevante.)

Un'altra risposta indica che l'utilizzo di una stringa di formato può semplificare il supporto per più lingue. Questo è vero, anche se ci sono dei limiti su ciò che puoi fare rispetto a cose come plurali, generi e così via.

+1

Grazie per la spiegazione dettagliata, mi ha aiutato a riflettere. Ho intenzione di andare con String.format come è a) una soluzione integrata eb) già rendendo la mia vita più semplice rendendo le stringhe molto più leggibili. – two13

-1

Credo che String.format sembri più pulito. Tuttavia, è possibile utilizzare StringBuilder e utilizzare la funzione append per creare lo strin desiderato.

1

Concatenando con plus, il compilet può trasformare il codice in modo performativo. Con il formato stringa non lo so.

Preferisco la cocatenazione con plus, penso che sia più semplice da sottomettere.

0

Sarò onesto e suggerisco di prendere il primo se si desidera meno digitando, o il secondo se si sta cercando un modo in più stile C. di farlo.

Mi sono seduto qui per un minuto o due riflettendo sull'idea di quello che potrebbe essere un problema, ma penso che dipenda da quanto si vuole digitare.

Qualcun altro ha un'idea?

+0

Il mio ragionamento dietro è più sulla leggibilità. Sono abbastanza abituato a digitare "roba" + "altre cose" e probabilmente dovrò rompere con quell'abitudine se vado con un'altra opzione. Quello che pensavo inizialmente era qualcosa come "Tu [verbo] a [utente] [testo]" e fai un replaceall (guidato dalla classe, quindi aggiungerei le variabili come setElement ("verbo", verbo) e poi sputerebbe indietro una stringa formattata), ma incappato in .format e ho capito che la mia idea originale sarebbe stata terribile con le prestazioni (ma super facile da leggere). – two13

0

Supponendo che si sta per riutilizzare le stringhe di base spesso memorizzare i vostri modelli come

String mystring = "Hai $ 1 a $ 2 \" $ 3 \ ""

Poi basta ottenere una copia e fare una sostituzione $ X con quello che vuoi

Ciò funzionerebbe davvero bene anche per un file di risorse.

+1

Inoltre, è possibile supportare più lingue: http://download.oracle.com/javase/tutorial/i18n/resbundle/concept.html –

-2

Il migliore, in termini di prestazioni, sarebbe probabilmente quello di utilizzare un StringBuffer.

+1

Non concordo. Da ['StringBuilder'] (http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html) javadoc: Dove possibile, si consiglia di utilizzare questa classe in preferenza a 'StringBuffer' in quanto sarà più veloce nella maggior parte delle implementazioni. --- Btw., Dubito che la concatenazione di stringhe sia il collo di bottiglia di un'applicazione del genere. – michael667

+1

Stessa differenza, una sincronizzata, una non. Quando la sincronizzazione viene implementata correttamente, la differenza è trascurabile se non c'è contesa.(E, ovviamente, non si vorrebbe usare StringBuilder se c'è contesa.) –

1

La chiave per mantenerla semplice è non guardarla mai. Ecco cosa intendo:

Joiner join = Joiner.on(" "); 

public void constructMessage(StringBuilder sb, Iterable<String> words) { 
    join.appendTo(sb, words); 
} 

Sto usando la classe Guava Joiner per rendere la leggibilità un non-problema. Cosa potrebbe essere più chiaro di "join"? Tutti i brutti frammenti riguardanti la concatenazione sono ben nascosti. Usando Iterable, posso usare questo metodo con tutti i tipi di strutture dati, le liste sono le più ovvie.

Ecco un esempio di una chiamata che utilizza una Guava ImmutableList (che è più efficiente di un elenco normale, poiché qualsiasi metodo che modifica l'elenco genera eccezioni e rappresenta correttamente il fatto che constructMessage() non può modificare l'elenco di parole, solo consumano):

StringBuilder outputMessage = new StringBuilder(); 
constructMessage(outputMessage, 
     new ImmutableList.Builder<String>() 
      .add("You", verb, "to", user, "\"", text, "\"") 
      .build()); 
0

Penso che la concatenazione con + è più leggibile rispetto all'utilizzo String.format.

String.format è buono quando è necessario formattare numero e date.