Fondamentalmente, l'uso di un ciclo per scorrere l'iter ArrayList
è l'unica opzione:
NON utilizzare questo codice, continua a leggere fino alla fine di questa risposta per vedere perché non è desiderabile e quale codice dovrebbe essere utilizzato invece:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
String listString = "";
for (String s : list)
{
listString += s + "\t";
}
System.out.println(listString);
In effetti, una concatenazione di stringhe andrà bene, dato che il javac
compilatore ottimizzerà la concatenazione di stringhe come una serie di append
operazioni su un StringBuilder
comunque. Ecco una parte dello smontaggio del bytecode dal for
loop dal programma sopra:
61: new #13; //class java/lang/StringBuilder
64: dup
65: invokespecial #14; //Method java/lang/StringBuilder."<init>":()V
68: aload_2
69: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: aload 4
74: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
77: ldc #16; //String \t
79: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
82: invokevirtual #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
Come si può vedere, il compilatore ottimizza quel loop usando un StringBuilder
, quindi le prestazioni non dovrebbero essere una grande preoccupazione.
(OK, a un secondo sguardo, StringBuilder
viene istanziato su ogni iterazione del loop, quindi potrebbe non essere il bytecode più efficiente. L'istanza e l'uso di un esplicito StringBuilder
probabilmente produrrebbe prestazioni migliori.)
In effetti, penso che avere qualsiasi tipo di output (sia esso su disco o sullo schermo) sarà almeno di un ordine di grandezza più lento rispetto a doversi preoccupare delle prestazioni delle concatenazioni di stringhe.
Modifica: come sottolineato nei commenti, l'ottimizzazione del compilatore sopra sta effettivamente creando una nuova istanza di StringBuilder
ogni iterazione. (Che ho notato in precedenza.)
La tecnica più ottimizzata da utilizzare sarà la risposta di Paul Tomblin , in quanto crea un'istanza di un singolo StringBuilder
oggetto all'esterno del for
loop.
Riscrivere il codice sopra per:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder();
for (String s : list)
{
sb.append(s);
sb.append("\t");
}
System.out.println(sb.toString());
Istituirà solo StringBuilder
una volta l'esterno del ciclo e effettuerà solo le due chiamate al append
metodo all'interno del ciclo, come evidenziato in questo bytecode (che mostra l'istanza di StringBuilder
e il ciclo):
// Instantiation of the StringBuilder outside loop:
33: new #8; //class java/lang/StringBuilder
36: dup
37: invokespecial #9; //Method java/lang/StringBuilder."<init>":()V
40: astore_2
// [snip a few lines for initializing the loop]
// Loading the StringBuilder inside the loop, then append:
66: aload_2
67: aload 4
69: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: pop
73: aload_2
74: ldc #15; //String \t
76: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
79: pop
Quindi, in effetti l'ottimizzazione della mano dovrebbe essere più performante, poiché l'interno del for
ciclo è più breve e non è necessario creare un'istanza StringBuilder
su ogni iterazione.