Ich habe eine ArrayList
, die ich komplett als String ausgeben möchte. Im Wesentlichen möchte ich es in der Reihenfolge ausgeben, in toString
der jedes Element durch Tabulatoren getrennt ist. Gibt es einen schnellen Weg, dies zu tun? Sie könnten es durchlaufen (oder jedes Element entfernen) und es zu einem String verketten, aber ich denke, das wird sehr langsam sein.
353
Antworten:
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:
Tatsächlich ist eine Zeichenfolgenverkettung in Ordnung, da der
javac
Compiler die Zeichenfolgenverkettung ohnehin als eine Reihe vonappend
Operationen für eine optimiertStringBuilder
. Hier ist ein Teil der Demontage des Bytecodes aus derfor
Schleife aus dem obigen Programm: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 CodesStringBuilder
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 derfor
Schleife instanziiert wird.Umschreiben des obigen Codes auf:
Instanziiert nur
StringBuilder
einmal außerhalb der Schleife und führt nur die beiden Aufrufe derappend
Methode innerhalb der Schleife durch, wie in diesem Bytecode (der die InstanziierungStringBuilder
und die Schleife zeigt) belegt:In der Tat sollte die Handoptimierung eine bessere Leistung erbringen, da das Innere der
for
Schleife kürzer ist und nichtStringBuilder
bei jeder Iteration ein instanziiert werden muss.quelle
Java
oder Geewax nachAndroid
In Java 8 oder höher:
Falls der
list
nicht vom Typ String ist, kann ein Verbindungskollektor verwendet werden:quelle
Wenn Sie dies zufällig auf Android tun, gibt es dafür ein nettes Dienstprogramm namens TextUtils, das eine
.join(String delimiter, Iterable)
Methode hat.Offensichtlich nicht viel Verwendung außerhalb von Android, aber ich dachte, ich würde es diesem Thread hinzufügen ...
quelle
TextUtils.join
dauert einObject[]
, würde ich annehmen, dass estoString()
auf jedem Token aufruft . HatPatientDetails
zu implementierentoString()
? Wenn das Problem dadurch nicht gelöst wird, können Sie möglicherweise etwas mit derSeparator
Klasse anfangen.org.apache.lang3.StringUtils
macht praktisch das gleiche, so dass Ihre Antwort für mich außerhalb von Android absolut von großem Nutzen war :)Laden Sie die Apache Commons Lang herunter und verwenden Sie die Methode
Sie können es natürlich selbst implementieren, aber der Code ist vollständig getestet und wahrscheinlich die bestmögliche Implementierung.
Ich bin ein großer Fan der Apache Commons-Bibliothek und ich denke auch, dass sie eine großartige Ergänzung zur Java Standard Library ist.
quelle
StringUtils.join(list.toArray(),"\t")
Dies ist eine ziemlich alte Frage, aber ich denke, ich könnte genauso gut eine modernere Antwort hinzufügen - verwenden Sie die
Joiner
Klasse aus Guave :quelle
Das Ändern der Liste in eine lesbare und aussagekräftige Zeichenfolge ist eine häufig gestellte Frage, auf die jeder stoßen kann.
Fall 1 . Wenn Sie Apaches StringUtils in Ihrem Klassenpfad haben (wie von Rogerdpack und Ravi Wallau):
Fall 2 . Wenn Sie nur Wege aus JDK (7) verwenden möchten:
Bauen Sie niemals Räder selbst, verwenden Sie keine Schleife für diese einzeilige Aufgabe.
quelle
Arrays.toString(myList.toArray())
- die einfachste und einfachste LösungArrays.toString(list.toArray())
ist leicht zu schreiben, aber sehr ineffizient.Wenn Sie nach einem schnellen Einzeiler suchen, können Sie ab Java 5 Folgendes tun:
Wenn Sie nur den Inhalt ausdrucken möchten und sich weniger Gedanken über das "\ t" machen, können Sie dies einfach tun:
was eine Zeichenfolge wie zurückgibt
Wenn Sie ein Array (nicht ArrayList) haben, können Sie dasselbe wie folgt erreichen:
quelle
m
Haushalten inn
Städten inx
Bundesstaaten suchen sollen , würden Sie sagen, dass esO(mnx)
oder istO(n^3)
, aber ich kann es umformulieren, um zu sagen: "Suchen Sie nach dieser Person in diesem Land", und Sie würden es mir sofort sagenO(n)
. Darüber hinaus gibt es bei allen Algorithmen im AllgemeinenO(n)
keine Schleife innerhalb einer Schleife.Durchlaufen Sie es und rufen Sie String auf. Es gibt keinen magischen Weg, und wenn ja, was würde er Ihrer Meinung nach unter der Decke tun, außer ihn zu durchlaufen? Die einzige Mikrooptimierung wäre die Verwendung von StringBuilder anstelle von String, und selbst das ist kein großer Gewinn - das Verketten von Strings wird unter dem Deckmantel zu StringBuilder, aber zumindest wenn Sie es so schreiben, können Sie sehen, was los ist.
quelle
In den meisten Java-Projekten steht häufig Apache-Commons-Sprache zur Verfügung. Die Methoden von StringUtils.join () sind sehr nett und bieten verschiedene Varianten, um fast alle Anforderungen zu erfüllen.
quelle
join(...)
Methode Varianten sowohl für Arrays als auch für Sammlungen enthält.Android verfügt über eine TextUtil-Klasse, die Sie unter http://developer.android.com/reference/android/text/TextUtils.html verwenden können
quelle
Für diesen einfachen Anwendungsfall können Sie die Zeichenfolgen einfach mit Komma verbinden. Wenn Sie Java 8 verwenden:
Andernfalls hat commons-lang eine join () -Methode:
quelle
Eine elegante Möglichkeit, mit nachgestellten Trennzeichen umzugehen, ist die Verwendung des Klassentrennzeichens
Die toString-Methode von Class Separator gibt das Separator mit Ausnahme des ersten Aufrufs zurück. Daher drucken wir die Liste ohne nachfolgende (oder in diesem Fall) führende Trennzeichen.
quelle
In Java 8 ist es einfach. Siehe Beispiel für eine Liste von Ganzzahlen:
Oder eine mehrzeilige Version (die einfacher zu lesen ist):
Update - eine kürzere Version
quelle
filter
. Am Ende fällt es mir viel leichter, den Code zu lesen.String
. Wenn es eine Liste vonInteger
s ist, haben Sie ein ProblemEs ist so oder so ein
O(n)
Algorithmus (es sei denn, Sie haben eine Multithread-Lösung durchgeführt, bei der Sie die Liste in mehrere Unterlisten aufgeteilt haben, aber ich denke nicht, dass Sie danach fragen).Verwenden Sie einfach ein
StringBuilder
wie folgt:Das
StringBuilder
wird viel schneller als String - Verkettung, weil Sie nicht wieder Instanziieren ein seinString
Objekt auf jeder Verkettung.quelle
Für den Fall, dass Sie gerade auf Android sind und Jack noch nicht verwenden (z. B. weil Instant Run noch nicht unterstützt wird) und wenn Sie mehr Kontrolle über die Formatierung der resultierenden Zeichenfolge wünschen (z. B. möchten Sie das Zeilenumbruchzeichen als verwenden der Teiler der Elemente) und zufällig die StreamSupport-Bibliothek verwenden / verwenden möchten (für die Verwendung von Streams unter Java 7 oder früheren Versionen des Compilers), könnten Sie Folgendes verwenden (ich habe diese Methode in meine ListUtils-Klasse eingefügt):
Stellen Sie natürlich sicher, dass Sie toString () in der Klasse Ihrer Listenobjekte implementieren.
quelle
reduce
ist für die Verkettung von Zeichenfolgen äußerst ineffizient. Sie sollten dies auf die Java 8-Methode tun,return StreamSupport.stream(list).map(Object::toString).collect(joining("\n"))
die intern verwendet wirdStringJoiner
. Es gibt keinen Grund, warum Sie dies nicht auch mit Streamsupport tun könnten .Optional#get
) fehlschlagen würde, wenn er eine leere Liste übergeben wird.Wenn Sie das letzte \ t nach dem letzten Element nicht möchten, müssen Sie den Index verwenden, um dies zu überprüfen. Beachten Sie jedoch, dass dies nur "funktioniert" (dh O (n)), wenn Listen den RandomAccess implementieren.
quelle
Der folgende Code kann Ihnen helfen,
Ausgabe:
quelle
Vielleicht nicht der beste, aber elegante Weg.
Arrays.deepToString (Arrays.asList ("Test", "Test2")
Ausgabe
[Test, Test2]
quelle
Wäre folgendes gut:
quelle
Wenn Sie Eclipse-Sammlungen verwenden , können Sie die
makeString()
Methode verwenden.Wenn Sie Ihre
ArrayList
in a konvertieren könnenFastList
, können Sie den Adapter entfernen.Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.
quelle
Sie übergeben die
new StringJoiner
Zeichenfolge, die Sie als Trennzeichen verwenden möchten. Wenn Sie eine CSV erstellen möchten:new StringJoiner(", ");
quelle
In einer Zeile: Von [12,0,1,78,12] bis 12 0 1 78 12
quelle
Zum Trennen mithilfe von Registerkarten anstelle von println können Sie print verwenden
quelle
Ich sehe einige Beispiele, die von zusätzlichen Ressourcen abhängen, aber es scheint, dass dies die einfachste Lösung wäre: (was ich in meinem eigenen Projekt verwendet habe), die im Grunde nur von einer ArrayList in ein Array und dann in eine Liste konvertiert .
quelle
Dies ist mittlerweile eine ziemlich alte Konversation, und Apache Commons verwenden jetzt intern einen StringBuilder: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/StringUtils.html#line. 3045
Dies wird bekanntlich die Leistung verbessern. Wenn die Leistung jedoch kritisch ist, ist die verwendete Methode möglicherweise etwas ineffizient. Während die Benutzeroberfläche flexibel ist und ein konsistentes Verhalten über verschiedene Sammlungstypen hinweg ermöglicht, ist sie für Listen, die der Sammlungstyp in der ursprünglichen Frage ist, etwas ineffizient.
Ich begründe dies damit, dass wir einen gewissen Overhead verursachen, den wir vermeiden würden, indem wir einfach die Elemente in einer traditionellen for-Schleife durchlaufen. Stattdessen passieren hinter den Kulissen einige zusätzliche Dinge, die auf gleichzeitige Änderungen, Methodenaufrufe usw. prüfen. Die erweiterte for-Schleife führt andererseits zu demselben Overhead, da der Iterator für das Iterable-Objekt (die Liste) verwendet wird.
quelle
Sie können hierfür einen Regex verwenden. Dies ist so kurz wie es nur geht
quelle
Wie wäre es mit dieser Funktion:
es funktioniert für jede Art von Sammlung ...
quelle