Grundsätzlich ist die Verwendung einer Schleife zum Iterieren über ArrayList
die einzige Option:
Verwenden Sie diesen Code NICHT. Lesen Sie weiter bis zum Ende dieser Antwort, um festzustellen, warum dies nicht wünschenswert ist und welcher Code stattdessen verwendet werden sollte:
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);
Tatsächlich ist eine Zeichenfolgenverkettung in Ordnung, da der javac
Compiler die Zeichenfolgenverkettung ohnehin als eine Reihe von append
Operationen für eine optimiert StringBuilder
. Hier ist ein Teil der Demontage des Bytecodes aus der for
Schleife aus dem obigen Programm:
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;
Wie zu sehen ist, optimiert der Compiler diese Schleife mithilfe von a StringBuilder
, sodass die Leistung kein großes Problem darstellen sollte.
(OK, auf den zweiten Blick wird das StringBuilder
bei jeder Iteration der Schleife instanziiert, sodass es möglicherweise nicht der effizienteste Bytecode ist. Das Instanziieren und Verwenden eines expliziten Codes StringBuilder
würde wahrscheinlich zu einer besseren Leistung führen.)
Tatsächlich denke ich, dass jede Art von Ausgabe (sei es auf der Festplatte oder auf dem Bildschirm) mindestens eine Größenordnung langsamer ist, als sich um die Leistung von String-Verkettungen sorgen zu müssen.
Bearbeiten: Wie in den Kommentaren erwähnt, erstellt die obige Compileroptimierung tatsächlich StringBuilder
bei jeder Iteration eine neue Instanz von . (Was ich zuvor bemerkt habe.)
Die am besten optimierte Technik ist die Antwort von Paul Tomblin , da nur ein einzelnes StringBuilder
Objekt außerhalb der for
Schleife instanziiert wird.
Umschreiben des obigen Codes auf:
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());
Instanziiert nur StringBuilder
einmal außerhalb der Schleife und führt nur die beiden Aufrufe der append
Methode innerhalb der Schleife durch, wie in diesem Bytecode (der die Instanziierung StringBuilder
und die Schleife zeigt) belegt:
// 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
In der Tat sollte die Handoptimierung eine bessere Leistung erbringen, da das Innere der for
Schleife kürzer ist und nicht StringBuilder
bei jeder Iteration ein instanziiert werden muss.