[java] Using Java 8 to convert a list of objects into a string obtained from the toString() method

There are a lot of useful new things in Java 8. E.g., I can iterate with a stream over a list of objects and then sum the values from a specific field of the Object's instances. E.g.

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

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

Thus, I'm asking if there is any way to build a String that concatenates the output of the toString() method from the instances in a single line.

List<Integer> list = ...

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

Suppose that list contains integers 1, 2 and 3, I expect that concatenated is "123" or "1,2,3".

This question is related to java java-8 java-stream

The answer is


String actual = list.stream().reduce((t, u) -> t + "," + u).get();

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

Or

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

This approach allows you also build a string result from a list of objects Example

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

Here the reduce function allows you to have some initial value to which you want to append new string Example:

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

Also, you can do like this.

    List<String> list = Arrays.asList("One", "Two", "Three");
    String result = String.join(", ", list);
    System.out.println(result);

Just in case anyone is trying to do this without java 8, there is a pretty good trick. List.toString() already returns a collection that looks like this:

[1,2,3]

Depending on your specific requirements, this can be post-processed to whatever you want as long as your list items don't contain [] or , .

For instance:

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

or if your data might contain square brackets this:

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

will get you a pretty reasonable output.

One array item on each line can be created like this:

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

I used this technique to make html tooltips from a list in a small app, with something like:

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

If you have an array then start with Arrays.asList(list).toString() instead

I'll totally own the fact that this is not optimal, but it's not as inefficient as you might think and is pretty straightforward to read and understand. It is, however, quite inflexible--in particular don't try to separate the elements with replaceAll if your data might contain commas and use the substring version if you have square brackets in your data, but for an array of numbers it's pretty much perfect.


There is a collector joining in the API. It's a static method in Collectors.

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

Not perfect because of the necessary call of toString, but works. Different delimiters are possible.


Can we try this.

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);

    }

I'm going to use the streams api to convert a stream of integers into a single string. The problem with some of the provided answers is that they produce a O(n^2) runtime because of String building. A better solution is to use a StringBuilder, and then join the strings together as the final step.

//              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();

You can take this process a step further by converting the collection of object to a single string.

// 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();

There is a method in the String API for those "joining list of string" usecases, you don't even need Stream.

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

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

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

Testing both approaches suggested in Shail016 and bpedroso answer (https://stackoverflow.com/a/24883180/2832140), the simple StringBuilder + append(String) within a for loop, seems to execute much faster than list.stream().map([...].

Example: This code walks through a Map<Long, List<Long>> builds a json string, using 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());
}

On my dev VM, junit usually takes between 0.35 and 1.2 seconds to execute the test. While, using this following code, it takes between 0.15 and 0.33 seconds:

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());
}

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


With Java 8+

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

Not the most efficient, but it is a solution with a small amount of code.


The other answers are fine. However, you can also pass Collectors.toList() as parameter to Stream.collect() to return the elements as an ArrayList.

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

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to java-8

Default interface methods are only supported starting with Android N Class has been compiled by a more recent version of the Java Environment Why is ZoneOffset.UTC != ZoneId.of("UTC")? Modify property value of the objects in list using Java 8 streams How to use if-else logic in Java 8 stream forEach Android Studio Error: Error:CreateProcess error=216, This version of %1 is not compatible with the version of Windows you're running Error:could not create the Java Virtual Machine Error:A fatal exception has occured.Program will exit What are functional interfaces used for in Java 8? java.time.format.DateTimeParseException: Text could not be parsed at index 21 Java 8 lambda get and remove element from list

Examples related to java-stream

Sorting a list with stream.sorted() in Java Modify property value of the objects in list using Java 8 streams How to use if-else logic in Java 8 stream forEach Java 8 lambda get and remove element from list Create list of object from another using Java 8 Streams Java 8 Stream API to find Unique Object matching a property value Reverse a comparator in Java 8 Ignore duplicates when producing map using streams Modifying Objects within stream in Java8 while iterating How can I get a List from some class properties with Java 8 Stream?