Verwenden von Streams zum Konvertieren einer Liste von Objekten in eine Zeichenfolge, die von der toString-Methode erhalten wurde

Lesezeit: 6 Minuten

Benutzer-Avatar
mat_junge

Es gibt viele nützliche neue Dinge in Java 8. Beispielsweise kann ich mit einem Stream über eine Liste von Objekten iterieren und dann die Werte aus einem bestimmten Feld der Object‘s Instanzen. Z.B

public class AClass {
  private int value;
  public int getValue() { return value; }
}

Integer sum = list.stream().mapToInt(AClass::getValue).sum();

Daher frage ich, ob es eine Möglichkeit gibt, eine zu bauen String die die Ausgabe von verkettet toString() -Methode aus den Instanzen in einer einzelnen Zeile.

List<Integer> list = ...

String concatenated = list.stream().... //concatenate here with toString() method from java.lang.Integer class

Nehme an, dass list enthält ganze Zahlen 1, 2 und 3das erwarte ich concatenated ist "123" oder "1,2,3".

  • Mögliches Duplikat von Java: Konvertiere List in einen String

    – Wadzim

    20. November 2017 um 19:25 Uhr

Benutzer-Avatar
Shail016

Eine einfache Möglichkeit besteht darin, Ihre Listenelemente in a anzuhängen StringBuilder

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

StringBuilder b = new StringBuilder();
list.forEach(b::append);

System.out.println(b);

Sie können auch versuchen:

String s = list.stream().map(e -> e.toString()).reduce("", String::concat);

Erklärung: map wandelt Integer-Stream in String-Stream um und wird dann als Verkettung aller Elemente reduziert.

Hinweis: Dies ist normal reduction was in O(n2)

Verwenden Sie für eine bessere Leistung a StringBuilder oder mutable reduction ähnlich der Antwort von F. Böller.

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

Ref: Stream-Reduzierung

  • Ja, keine Inline-Lösung, sondern eine Lösung.

    – mat_boy

    22. Juli 2014 um 9:18 Uhr

  • habe das nicht verstanden. Was erwarten Sie?

    – Shail016

    22. Juli 2014 um 9:20 Uhr

  • Ich verstehe nicht, warum “normale Reduktion, die in O (n2) durchführt”. für mich “sieht” es eher nach O(n) aus…

    – Datahaki

    15. März 2017 um 12:55 Uhr

  • @datahaki Ich bin kein Java-Typ, aber ich würde vermuten, dass die iterative String-Verkettung (Reduktion) bei jeder Iteration eine (Neu-) Zuordnung von Arrays erfordert, was es zu O (n ^ 2) macht. join Auf der anderen Seite würde ein einzelnes Array vorbelegt, das groß genug ist, um die letzte Zeichenfolge zu speichern, bevor es gefüllt wird, wodurch es O (n) wird.

    – Eli Korvigo

    18. Januar 2018 um 14:44 Uhr


  • Sehr guter Tipp. Vielleicht können Sie mit der Notation “::” vereinfachen. So, list.stream().map(Object::toString).reduce("", String::concat). Verwenden map e-> e.toString() ist etwas überflüssig.

    – e2a

    9. Februar 2018 um 13:02 Uhr


Benutzer-Avatar
F.Böller

Es gibt einen Sammler joining in der API. Es ist eine statische Methode in Collectors.

list.stream().map(Object::toString).collect(Collectors.joining(","))

Nicht perfekt wegen des notwendigen Aufrufs von toString, funktioniert aber. Es sind verschiedene Trennzeichen möglich.

  • Der Vollständigkeit halber: Damit genau dieser Code funktioniert, müssen Sie import static java.util.stream.Collectors.joining;

    – Mahdi

    24. Februar 2016 um 10:36 Uhr

  • Warum brauchen wir das Mapping und das explizite `toString’? Wenn der Kollektor String-Elemente erwartet, sollte die Konvertierung implizit aufgerufen werden, oder?!

    – Basler Shishani

    5. September 2016 um 3:41 Uhr

Benutzer-Avatar
Bill K

Für den Fall, dass jemand versucht, dies ohne Java 8 zu tun, gibt es einen ziemlich guten Trick. List.toString() gibt bereits eine Sammlung zurück, die so aussieht:

[1,2,3]

Abhängig von Ihren spezifischen Anforderungen kann dies beliebig nachbearbeitet werden, solange Ihre Listenelemente nicht enthalten sind [] oder , .

Zum Beispiel:

list.toString().replace("[","").replace("]","") 

oder wenn Ihre Daten eckige Klammern enthalten könnten, dies:

String s=list.toString();
s = s.substring(1,s.length()-1) 

erhalten Sie eine ziemlich vernünftige Ausgabe.

Ein Array-Element in jeder Zeile kann wie folgt erstellt werden:

list.toString().replace("[","").replace("]","").replaceAll(",","\r\n")

Ich habe diese Technik verwendet, um HTML-Tooltips aus einer Liste in einer kleinen App zu erstellen, mit etwas wie:

list.toString().replace("[","<html>").replace("]","</html>").replaceAll(",","<br>")

Wenn Sie ein Array haben, beginnen Sie stattdessen mit Arrays.asList(list).toString()

Ich gebe zu, dass dies nicht optimal ist, aber es ist nicht so ineffizient, wie Sie vielleicht denken, und es ist ziemlich einfach zu lesen und zu verstehen. Es ist jedoch ziemlich unflexibel – versuchen Sie insbesondere nicht, die Elemente mit replaceAll zu trennen, wenn Ihre Daten Kommas enthalten könnten, und verwenden Sie die Substring-Version, wenn Sie eckige Klammern in Ihren Daten haben, aber für ein Array von Zahlen ist es ziemlich viel perfekt.

  • Obwohl dies normalerweise funktioniert, ist es nicht garantiert – List erzwingt nicht die Struktur von toString(). AbstractCollection verwendet diese Struktur jedoch standardmäßig, und ich denke, alle für den allgemeinen Zweck List Implementierungen in Java SE tun dies ebenfalls. Als Beispiel für eines, das dies nicht tut, org.springframework.util.AutoPopulatingList in Spring nicht implementiert toString() und würde somit zB zurückgeben “[email protected]“.

    – M. Justin

    17. April 2020 um 20:12 Uhr

  • Arrays.toString() wäre eine bessere Wahl als Arrays.asList(list).toString()da es so definiert ist, dass es eine äquivalente Zeichenfolge zurückgibt, ist es prägnanter und erfordert keine zusätzliche Objekterstellung.

    – M. Justin

    17. April 2020 um 20:15 Uhr

  • @M.Justin Kein schlechter Punkt für den Array-Teil dieser Antwort, aber was ist mit einer einfachen “Liste”? Sie können Arrays.toString() dafür nicht wirklich verwenden. Wie würden Sie vorschlagen, diese Technik auf so etwas wie die von Ihnen erwähnte AutoPopulatingList anzuwenden? Vielleicht: new ArrayList(autoPopulatingList).toString()? Oder ich denke, Sie könnten es in ein Array umwandeln. Wenn Sie auf ein solches Problem gestoßen sind, sollten Sie vielleicht hoffen, dass Sie auf 1.8 oder höher sind und eine der anderen Antworten in diesem Thread verwenden könnten …

    – Bill K

    20. April 2020 um 22:13 Uhr


Es gibt eine Methode in der String-API für diese Anwendungsfälle „Joining List of String“, Sie brauchen nicht einmal Stream.

List<String> myStringIterable = Arrays.asList("baguette", "bonjour");

String myReducedString = String.join(",", myStringIterable);

// And here you obtain "baguette,bonjour" in your myReducedString variable

Benutzer-Avatar
Edward J. Beckett

Die anderen Antworten sind in Ordnung. Sie können aber auch bestehen Collectors.toList() als Parameter zu Stream.collect() um die Elemente als ArrayList zurückzugeben.

System.out.println( list.stream().map( e -> e.toString() ).collect( toList() ) );

  • Wenn du benutzt System.out.print(ln)(list) es wird die verwenden toString() Methode der Elemente, um die Liste zu drucken. Dieser Code wiederholt also nur, was im Inneren passiert toString von Liste.

    – Shirkam

    24. Oktober 2017 um 13:26 Uhr

  • Sollte Collectors.toList() sein, es sei denn, Sie importieren statisch.

    – mwieczorek

    5. April 2018 um 15:56 Uhr

  • Yep … Ich habe Static für das Beispiel importiert. Ich habe im Hauptteil der Antwort “Collectors.toList()” angegeben … 😉

    – Edward J. Beckett

    5. April 2018 um 16:38 Uhr

Benutzer-Avatar
Rekha Ghanate

StringListName = ObjectListName.stream().map( m -> m.toString() ).collect( Collectors.toList() );

  • Wenn du benutzt System.out.print(ln)(list) es wird die verwenden toString() Methode der Elemente, um die Liste zu drucken. Dieser Code wiederholt also nur, was im Inneren passiert toString von Liste.

    – Shirkam

    24. Oktober 2017 um 13:26 Uhr

  • Sollte Collectors.toList() sein, es sei denn, Sie importieren statisch.

    – mwieczorek

    5. April 2018 um 15:56 Uhr

  • Yep … Ich habe Static für das Beispiel importiert. Ich habe im Hauptteil der Antwort “Collectors.toList()” angegeben … 😉

    – Edward J. Beckett

    5. April 2018 um 16:38 Uhr

Benutzer-Avatar
0vint0

List<String> list = Arrays.asList("One", "Two", "Three");
    list.stream()
            .reduce("", org.apache.commons.lang3.StringUtils::join);

Oder

List<String> list = Arrays.asList("One", "Two", "Three");
        list.stream()
                .reduce("", (s1,s2)->s1+s2);

Mit diesem Ansatz können Sie auch ein Zeichenfolgenergebnis aus einer Liste von Objekten erstellen. Beispiel

List<Wrapper> list = Arrays.asList(w1, w2, w2);
        list.stream()
                .map(w->w.getStringValue)
                .reduce("", org.apache.commons.lang3.StringUtils::join);

Hier können Sie mit der Reduce-Funktion einen Anfangswert haben, an den Sie eine neue Zeichenfolge anhängen möchten. Beispiel:

 List<String> errors = Arrays.asList("er1", "er2", "er3");
            list.stream()
                    .reduce("Found next errors:", (s1,s2)->s1+s2);

1014180cookie-checkVerwenden von Streams zum Konvertieren einer Liste von Objekten in eine Zeichenfolge, die von der toString-Methode erhalten wurde

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy