Ich habe eine ArrayList
die ich vollständig als String ausgeben möchte. Im Wesentlichen möchte ich sie in der Reihenfolge ausgeben, in der die toString
der einzelnen Elemente durch Tabulatoren getrennt. Gibt es eine schnelle Möglichkeit, dies zu tun? Sie könnten Schleife durch sie (oder entfernen Sie jedes Element) und verketten es zu einem String, aber ich denke, dies wird sehr langsam sein.
Antworten
Zu viele Anzeigen?Wenn Sie dies auf Android tun, gibt es ein nettes Dienstprogramm für diese Aufgabe namens TextUtils die eine .join(String delimiter, Iterable)
Methode.
List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);
Offensichtlich nicht viel Verwendung außerhalb von Android, aber dachte, ich würde es zu diesem Thread hinzufügen...
Java 8 führt eine String.join(separator, list)
Methode; siehe Vitalii Federenko's Antwort .
Vor Java 8 wurde eine Schleife zur Iteration über die ArrayList
war die einzige Möglichkeit:
Verwenden Sie diesen Code NICHT, lesen Sie weiter bis zum Ende dieser Antwort, um zu erfahren, warum er nicht erwünscht 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 String-Verkettung genau richtig, da die javac
Compiler optimiert die String-Verkettung als eine Reihe von append
Operationen auf einer StringBuilder
sowieso. Hier ist ein Teil der Disassemblierung des Bytecodes aus dem 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 man sieht, optimiert der Compiler diese Schleife durch die Verwendung einer StringBuilder
Die Leistung sollte also kein großes Problem darstellen.
(OK, auf den zweiten Blick ist die StringBuilder
wird bei jeder Iteration der Schleife instanziiert, so dass es sich möglicherweise nicht um den effizientesten Bytecode handelt. Die Instanziierung und Verwendung einer expliziten StringBuilder
würde wahrscheinlich eine bessere Leistung bringen).
Ich denke, dass jede Art von Ausgabe (sei es auf die Festplatte oder auf den Bildschirm) mindestens um eine Größenordnung langsamer ist, als wenn man sich um die Leistung von String-Verkettungen kümmern muss.
Edita: Wie in den Kommentaren erwähnt, erzeugt die obige Compiler-Optimierung tatsächlich eine neue Instanz von StringBuilder
bei jeder Iteration. (Was ich schon früher festgestellt habe.)
Die optimalste Technik ist die Antwort von Paul Tomblin da es nur eine einzige Instanzierung StringBuilder
Objekts außerhalb der for
Schleife.
Umschreiben des obigen Codes in:
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 die StringBuilder
einmal außerhalb der Schleife und führen nur die beiden Aufrufe an die append
Methode innerhalb der Schleife, wie in diesem Bytecode zu sehen ist (der die Instanziierung von StringBuilder
und die Schleife):
// 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
Die Handoptimierung sollte also in der Tat besser funktionieren, da das Innere des for
Schleife ist kürzer und es besteht keine Notwendigkeit, eine StringBuilder
bei jeder Iteration.
Laden Sie die Apache Commons Lang herunter und verwenden Sie die Methode
StringUtils.join(list)
StringUtils.join(list, ", ") // 2nd param is the separator.
Sie können es natürlich auch selbst implementieren, aber ihr Code ist vollständig getestet und stellt wahrscheinlich die bestmögliche Implementierung dar.
Ich bin ein großer Fan der Apache-Commons-Bibliothek und halte sie für eine großartige Ergänzung der Java-Standardbibliothek.
- See previous answers
- Weitere Antworten anzeigen