Użycie Javy 8 do konwersji listy obiektów na ciąg znaków uzyskany z metody toString()

W Javie 8 jest wiele nowych przydatnych rzeczy. Na przykład, mogę iterować strumieniem nad listą obiektów, a następnie zsumować wartości z określonego pola instancji Object. Np.

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

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

Dlatego pytam, czy istnieje jakiś sposób na zbudowanie String, który łączy wyjście metody toString() z instancji w jednej linii.

List<Integer> list = ...

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

Załóżmy, że list zawiera liczby całkowite 1, 2 i 3, spodziewam się, że concatenated jest "123" lub "1,2,3".

Author: Naman, 2014-07-22

13 answers

Jednym z prostych sposobów jest dodanie elementów listy w 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);
Możesz również spróbować:
String s = list.stream().map(e -> e.toString()).reduce("", String::concat);

Explanation: map zamienia strumień liczb całkowitych na strumień Łańcuchowy, a następnie jego redukcję jako konkatenację wszystkich elementów.

UWAGA: Jest to normal reduction, które występuje w O (n2)

Dla lepszej wydajności użyj StringBuilder lub mutable reduction podobnej do odpowiedzi F. Böllera.

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

Ref: Redukcja Strumienia

 405
Author: Shail016,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-18 14:36:14

W API znajduje się kolektor joining. Jest to metoda statyczna w Collectors.

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

Nie doskonałe ze względu na konieczne wezwanie toString, ale działa. Możliwe są różne ograniczniki.

 210
Author: F. Böller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-16 15:44:48

Na wypadek, gdyby ktoś próbował to zrobić bez Javy 8, jest całkiem niezła sztuczka. Lista.ToString () zwraca już kolekcję, która wygląda tak:

[1,2,3]

W zależności od twoich konkretnych wymagań, może to być przetwarzane do dowolnego, co chcesz, o ile elementy listy nie zawierają [] lub , .

Na przykład:

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

Lub jeśli Twoje dane mogą zawierać nawiasy kwadratowe to:

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

Da ci całkiem rozsądną wyjście.

Jeden element tablicy w każdej linii może być utworzony w następujący sposób:

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

Użyłem tej techniki do tworzenia podpowiedzi html z listy w małej aplikacji, z czymś takim:

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

Jeśli masz tablicę, zacznij od tablic.asList (lista).toString () zamiast

Będę całkowicie właścicielem faktu, że nie jest to optymalne, ale nie jest tak nieefektywne, jak mogłoby się wydawać i jest dość proste do odczytania i zrozumienia. Jest jednak dość nieelastyczny-w szczególności nie spróbuj oddzielić elementy za pomocą replaceAll, jeśli Twoje dane mogą zawierać przecinki i użyj wersji podłańcucha, jeśli masz nawiasy kwadratowe w danych, ale dla tablicy liczb jest to prawie idealne.

 9
Author: Bill K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-14 00:29:20

Pozostałe odpowiedzi są w porządku. Można jednak również przekazać kolekcjonerów.toList () jako parametr do strumienia .collect () zwraca elementy jako ArrayList.

System.out.println( list.stream().map( e -> e.toString() ).collect( toList() ) );
 6
Author: Eddie B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-18 09:22:11

Istnieje metoda W String API dla tych" łączenia listy łańcuchów", nawet nie potrzebujesz Stream.

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

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

// And here you obtain "baguette,bonjour" in your myReducedString variable
 4
Author: Bachrc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-27 09:59:11

StringListName = ObjectListName.strumień ().map( m -> m.toString() ).collect( kolekcjoner.toList ());

 3
Author: Rekha Ghanate,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-07 22:15:25
List<String> list = Arrays.asList("One", "Two", "Three");
    list.stream()
            .reduce("", org.apache.commons.lang3.StringUtils::join);

Lub

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

To podejście pozwala również zbudować wynik łańcuchowy z listy obiektów Przykład

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

Tutaj funkcja reduce pozwala mieć pewną wartość początkową, do której chcesz dołączyć nowy ciąg znaków Przykład:

 List<String> errors = Arrays.asList("er1", "er2", "er3");
            list.stream()
                    .reduce("Found next errors:", (s1,s2)->s1+s2);
 1
Author: 0vint0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 07:54:16

Testowanie obu podejść zaproponowanych w Shail016 i bpedroso answer ( https://stackoverflow.com/a/24883180/2832140 ), proste StringBuilder + append(String) W pętli for, wydaje się działać znacznie szybciej niż list.stream().map([...].

Przykład: Ten kod przechodzi przez Map<Long, List<Long>> buduje łańcuch json, używając list.stream().map([...]:

if (mapSize > 0) {
    StringBuilder sb = new StringBuilder("[");

    for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {

        sb.append("{\"" + entry.getKey().toString() + "\":[");
        sb.append(entry.getValue().stream().map(Object::toString).collect(Collectors.joining(",")));
    }
    sb.delete(sb.length()-2, sb.length());
    sb.append("]");
    System.out.println(sb.toString());
}

Na mojej maszynie wirtualnej junit zwykle trwa od 0,35 do 1,2 sekundy, aby wykonać test. Podczas gdy użycie poniższego kodu zajmuje od 0.15 do 0.33 sekund:

if (mapSize > 0) {
    StringBuilder sb = new StringBuilder("[");

    for (Map.Entry<Long, List<Long>> entry : threadsMap.entrySet()) {

        sb.append("{\"" + entry.getKey().toString() + "\":[");

        for (Long tid : entry.getValue()) {
            sb.append(tid.toString() + ", ");
        }
        sb.delete(sb.length()-2, sb.length());
        sb.append("]}, ");
    }
    sb.delete(sb.length()-2, sb.length());
    sb.append("]");
    System.out.println(sb.toString());
}
 1
Author: Lorenzo Cipriani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 15:31:48

Możemy spróbować?

public static void main(String []args){
        List<String> stringList = new ArrayList<>();
        for(int i=0;i< 10;i++){
            stringList.add(""+i);
        }
        String stringConcated = String.join(",", stringList);
        System.out.println(stringConcated);

    }
 0
Author: Kumar Abhishek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-22 13:09:22
String actual = list.stream().reduce((t, u) -> t + "," + u).get();
 0
Author: Joe Almore,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 11:46:38

Zamierzam użyć API streams do konwersji strumienia liczb całkowitych na pojedynczy ciąg znaków. Problem z niektórymi dostarczonymi odpowiedziami polega na tym, że wytwarzają one O (N^2) runtime z powodu budowania łańcuchów. Lepszym rozwiązaniem jest użycie StringBuilder, a następnie połączyć ze sobą ciągi jako ostatni krok.

//              Create a stream of integers 
    String result = Arrays.stream(new int[]{1,2,3,4,5,6 })                
            // collect into a single StringBuilder
            .collect(StringBuilder::new, // supplier function
                    // accumulator - converts cur integer into a string and appends it to the string builder
                    (builder, cur) -> builder.append(Integer.toString(cur)),
                    // combiner - combines two string builders if running in parallel
                    StringBuilder::append) 
            // convert StringBuilder into a single string
            .toString();

Możesz pójść o krok dalej, konwertując kolekcję obiektu na pojedynczy łańcuch znaków.

// Start with a class definition
public static class AClass {
    private int value;
    public int getValue() { return value; }
    public AClass(int value) { this.value = value; }

    @Override
    public String toString() {
        return Integer.toString(value);
    }
}

// Create a stream of AClass objects
        String resultTwo = Arrays.stream(new AClass[]{
                new AClass(1),
                new AClass(2),
                new AClass(3),
                new AClass(4)
        })
                // transform stream of objects into a single string
                .collect(StringBuilder::new,
                        (builder, curObj) -> builder.append(curObj.toString()),
                        StringBuilder::append
                )
            // finally transform string builder into a single string
            .toString();
 0
Author: Larry Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-25 01:32:25

Z Javą 8 +

String s = Arrays.toString(list.stream().toArray(AClass[]::new));

Nie najbardziej wydajny, ale jest to rozwiązanie z niewielką ilością kodu.

 -1
Author: James Wierzba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 00:23:31

Możesz też zrobić tak.

    List<String> list = Arrays.asList("One", "Two", "Three");
    String result = String.join(", ", list);
    System.out.println(result);
 -2
Author: Evgenii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 12:31:49