webentwicklung-frage-antwort-db.com.de

Beste Möglichkeit, eine ArrayList in einen String zu konvertieren

Ich habe ein ArrayList, das ich komplett als String ausgeben möchte. Im Wesentlichen möchte ich es in der Reihenfolge ausgeben, in der toString jedes Elements durch Tabulatoren getrennt wird. 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
Juan Besa

Grundsätzlich ist die Verwendung einer Schleife zum Iterieren über ArrayList die einzige Option:

Verwenden Sie diesen Code NICHT. Lesen Sie weiter unten in 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 Compiler javac die Zeichenfolgenverkettung ohnehin als eine Reihe von append -Operationen für StringBuilder optimiert. Hier ist ein Teil der Demontage des Bytecodes aus der for -Schleife des obigen Programms:

   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 StringBuilder, sodass die Leistung kein großes Problem darstellen sollte.

(OK, auf den zweiten Blick wird das StringBuilder bei jeder Iteration der Schleife instanziiert, daher ist es möglicherweise nicht der effizienteste Bytecode. Das Instantiieren und Verwenden eines expliziten 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 sein wird, als sich um die Leistung von Zeichenfolgenverkettungen sorgen zu müssen.

Bearbeiten: Wie in den Kommentaren ausgeführt, wird durch die oben genannte Compileroptimierung in der Tat bei jeder Iteration eine neue Instanz von StringBuilder erstellt. (Was ich vorher notiert habe.)

Die am besten geeignete Methode ist die Antwort von Paul Tomblin , da nur ein einzelnes StringBuilder -Objekt außerhalb der for -Schleife instanziiert wird.

Umschreiben des obigen Codes zu:

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 StringBuilder nur einmal außerhalb der Schleife und ruft die append -Methode nur innerhalb der Schleife auf, wie in diesem Bytecode gezeigt (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 tatsächlich eine bessere Leistung bringen, da das Innere der for -Schleife kürzer ist und nicht bei jeder Iteration eine StringBuilder instanziiert werden muss.

315
coobird

In Java 8 oder höher:

String listString = String.join(", ", list);

Falls das list nicht vom Typ String ist, kann ein Join-Collector verwendet werden:

String listString = list.stream().map(Object::toString)
                        .collect(Collectors.joining(", "));
789

Wenn Sie dies unter Android tun, gibt es ein Nizza-Dienstprogramm namens TextUtils , das eine .join(String delimiter, Iterable) -Methode hat.

List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);

Offensichtlich nicht viel außerhalb von Android zu verwenden, aber ich dachte, ich würde es zu diesem Thread hinzufügen ...

378
JJ Geewax

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 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 dies eine großartige Ergänzung der Java Standard-Bibliothek ist.

222
Ravi Wallau

Dies ist eine ziemlich alte Frage, aber ich schätze, ich könnte genauso gut eine modernere Antwort hinzufügen - benutze die Joiner Klasse von Guava :

String joined = Joiner.on("\t").join(list);
138
Jon Skeet

Das Ändern von 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):

import org.Apache.commons.lang3.StringUtils;
String str = StringUtils.join(myList);

Fall 2. Wenn Sie nur die Möglichkeiten von JDK (7) nutzen möchten:

import Java.util.Arrays;
String str = Arrays.toString(myList.toArray()); 

Bauen Sie niemals selbst Räder, verwenden Sie keine Schleife für diese einzeilige Aufgabe.

79
Sheng.W

Wenn Sie nach einem schnellen Einzeiler gesucht haben, können Sie dies ab Java 5 tun:

myList.toString().replaceAll("\\[|\\]", "").replaceAll(", ","\t")

Wenn Sie nur den Inhalt ausdrucken möchten und sich weniger Gedanken über das "\ t" machen, können Sie dies auch einfach tun:

myList.toString()

was eine Zeichenfolge wie zurückgibt

[str1, str2, str3]

Wenn Sie ein Array (nicht ArrayList) haben, können Sie dasselbe wie folgt ausführen:

 Arrays.toString(myList).replaceAll("\\[|\\]", "").replaceAll(", ","\t")
56
Ken Shih

Durchlaufen und toString aufrufen. Es gibt keinen magischen Weg, und wenn es einen gäbe, was denkst du, würde es unter der Decke anders machen, als es zu durchlaufen? Die einzige Mikrooptimierung wäre die Verwendung von StringBuilder anstelle von String, und selbst das ist kein großer Gewinn - die Verkettung von Strings wird zu StringBuilder unter der Decke, aber zumindest, wenn Sie es so schreiben, können Sie sehen, was los ist.

StringBuilder out = new StringBuilder();
for (Object o : list)
{
  out.append(o.toString());
  out.append("\t");
}
return out.toString();
38
Paul Tomblin

In den meisten Java Projekten ist häufig die Apache-commons-Sprache verfügbar. Die StringUtils.join () -Methode ist sehr gut und bietet verschiedene Varianten, um fast allen Anforderungen gerecht zu werden.

public static Java.lang.String join(Java.util.Collection collection,
                                    char separator)


public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer 
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }
    // two or more elements 
    StringBuffer buf = 
        new StringBuffer(256); // Java default is 16, probably too small 
    if (first != null) {
        buf.append(first);
    }
    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

Parameter:

collection - Die Sammlung der zusammenzufügenden Werte kann null sein

Trennzeichen - das zu verwendende Trennzeichen

Rückgabe: der verknüpfte String, null, wenn null, Iterator-Eingabe

Seit: 2.3

36
Brian

Android hat eine TextUtil-Klasse, die Sie verwenden können http://developer.Android.com/reference/Android/text/TextUtils.html

String implode = TextUtils.join("\t", list);
15
kehers

In diesem einfachen Anwendungsfall können Sie die Zeichenfolgen einfach mit Komma verbinden. Wenn Sie Java 8 verwenden:

String csv = String.join("\t", yourArray);

andernfalls hat commons-lang eine join () -Methode:

String csv = org.Apache.commons.lang3.StringUtils.join(yourArray, "\t");
14
Khader M A

Eine elegante Möglichkeit, mit nachgestellten Trennzeichen umzugehen, ist die Verwendung von Klassentrennzeichen

StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();

Die toString-Methode von Class Separator gibt das Trennzeichen mit Ausnahme von für den ersten Aufruf zurück. Daher drucken wir die Liste ohne nachfolgende (oder in diesem Fall) führende Trennzeichen.

13
akuhn

ArrayList Klasse ( Java Docs ) erweitert AbstractList Klasse, die AbstractCollection Klasse erweitert, die eine toString() Methode enthält ( Java Docs ). Also schreibst du einfach

listName.toString();

Java-Entwickler haben bereits den effizientesten Weg gefunden und Ihnen dies in einer gut verpackten und dokumentierten Methode vermittelt. Rufen Sie diese Methode einfach auf.

7
golddove

Es ist in beiden Fällen ein O(n) -Algorithmus (es sei denn, Sie haben eine Multithread-Lösung erstellt, bei der Sie die Liste in mehrere Unterlisten unterteilt haben, aber ich glaube nicht, dass Sie danach fragen).

Verwenden Sie einfach ein StringBuilder wie folgt:

StringBuilder sb = new StringBuilder();

for (Object obj : list) {
  sb.append(obj.toString());
  sb.append("\t");
}

String finalString = sb.toString();

Das StringBuilder ist viel schneller als die Verkettung von Zeichenfolgen, da Sie bei jeder Verkettung kein String -Objekt erneut instanziieren.

6
Mike C.

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 Sie mehr Kontrolle über die Formatierung der resultierenden Zeichenfolge haben möchten (z. B. wenn Sie möchten) Um das Newline-Zeichen als Teiler von Elementen zu verwenden und zufällig die StreamSupport-Bibliothek zu verwenden (für die Verwendung von Streams in Java 7 oder früheren Versionen des Compilers), können Sie so etwas verwenden (Ich habe diese Methode in meine ListUtils-Klasse aufgenommen):

public static <T> String asString(List<T> list) {
    return StreamSupport.stream(list)
            .map(Object::toString)
            .collect(Collectors.joining("\n"));
}

Und natürlich müssen Sie toString () in die Klasse Ihrer Listenobjekte implementieren.

5

In Java 8 ist es einfach. Siehe Beispiel für eine Liste von ganzen Zahlen:

String result = Arrays.asList(1,2,3).stream().map(Object::toString).reduce((t, u) -> t + "\t" + u).orElse("");

Oder mehrzeilige Version (die einfacher zu lesen ist):

String result = Arrays.asList(1,2,3).stream()
    .map(Object::toString)
    .reduce((t, u) -> t + "\t" + u)
    .orElse("");

Update - eine kürzere Version

String result = Arrays.asList(1,2,3).stream()
                .map(Object::toString)
                .collect(Collectors.joining("\t"));
4
amra

Wäre das Folgende etwas Gutes:

List<String> streamValues = new ArrayList<>();
Arrays.deepToString(streamValues.toArray()));   
3
Beezer

Wenn Sie nicht möchten, dass das letzte\t nach dem letzten Element steht, müssen Sie den Index verwenden, um dies zu überprüfen. Beachten Sie jedoch, dass dies nur "funktioniert" (dh O(n)) ist, wenn lists das implementiert RandomAccess.

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none
for (int i = 0; i < list.size(); i++) {
    sb.append(list.get(i));
    if (i < list.size() - 1) {
        sb.append("\t");
    }
}
System.out.println(sb.toString());
3
So So
List<String> stringList = getMyListOfStrings();
StringJoiner sj = new StringJoiner(" ");
stringList.stream().forEach(e -> sj.add(e));
String spaceSeparated = sj.toString()

Sie übergeben dem new StringJoiner die Zeichenfolge, die Sie als Trennzeichen verwenden möchten. Wenn Sie eine CSV-Datei erstellen möchten: new StringJoiner(", ");

3
fmsf

Der folgende Code kann Ihnen helfen,

List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
String str = list.toString();
System.out.println("Step-1 : " + str);
str = str.replaceAll("[\\[\\]]", "");
System.out.println("Step-2 : " + str);

Ausgabe:

Step-1 : [1, 2, 3]
Step-2 : 1, 2, 3
3
Srinivasan.S

Vielleicht nicht der beste Weg, aber elegant.

Arrays.deepToString (Arrays.asList ("Test", "Test2")

import Java.util.Arrays;

    public class Test {
        public static void main(String[] args) {
            System.out.println(Arrays.deepToString(Arrays.asList("Test", "Test2").toArray()));
        }
    }

Ausgabe

[Test, Test2]

3

Wenn Sie Eclipse Collections verwenden, können Sie die Methode makeString() verwenden.

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

Assert.assertEquals(
    "one\ttwo\tthree",
    ArrayListAdapter.adapt(list).makeString("\t"));

Wenn Sie Ihr ArrayList in ein FastList konvertieren können, können Sie den Adapter entfernen.

Assert.assertEquals(
    "one\ttwo\tthree",
    FastList.newListWith("one", "two", "three").makeString("\t"));

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.

3
Craig P. Motlin

Zum Trennen mit Tabulatoren anstelle von println können Sie print verwenden

ArrayList<String> mylist = new ArrayList<String>();

mylist.add("C Programming");
mylist.add("Java");
mylist.add("C++");
mylist.add("Perl");
mylist.add("Python");

for (String each : mylist)
{       
    System.out.print(each);
    System.out.print("\t");
}
2
chopss

Ich sehe einige Beispiele, die von zusätzlichen Ressourcen abhängen, aber es scheint, als wäre dies die einfachste Lösung: (die ich in meinem eigenen Projekt verwendet habe), die im Grunde nur von einer ArrayList in ein Array und dann in eine List konvertiert .

    List<Account> accounts = new ArrayList<>();

   public String accountList() 
   {
      Account[] listingArray = accounts.toArray(new Account[accounts.size()]);
      String listingString = Arrays.toString(listingArray);
      return listingString;
   }
1
Elliander

In einer Zeile: Von [12,0,1,78,12] bis 12 0 1 78 12

String srt= list.toString().replaceAll("\\[|\\]|,","");
0

Dies ist 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 bekanntermaßen die Leistung verbessern. Wenn die Leistung jedoch kritisch ist, ist die verwendete Methode möglicherweise ineffizient. Während die Benutzeroberfläche flexibel ist und ein konsistentes Verhalten für verschiedene Sammlungstypen ermöglicht, ist sie für Listen, bei denen es sich um die Art der Sammlung in der ursprünglichen Frage handelt, 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 nach gleichzeitigen Änderungen, Methodenaufrufen usw. suchen. Die erweiterte for-Schleife führt andererseits zu demselben Overhead, da der Iterator für das Iterable-Objekt (die Liste) verwendet wird.

0
Alex VI

Sie können dafür einen Regex verwenden. Dies ist so kurz wie es nur geht

System.out.println(yourArrayList.toString().replaceAll("\\[|\\]|[,][ ]","\t"));
0
Vikrant Goel