Best way to concatenate List of String objects?

JavaStringList

Java Problem Overview


What is the best way to concatenate a list of String objects? I am thinking of doing this way:

List<String> sList = new ArrayList<String>();

// add elements

if (sList != null)
{
    String listString = sList.toString();
    listString = listString.subString(1, listString.length() - 1);
}

I somehow found this to be neater than using the StringBuilder/StringBuffer approach.

Any thoughts/comments?

Java Solutions


Solution 1 - Java

Use one of the the StringUtils.join methods in Apache Commons Lang.

import org.apache.commons.lang3.StringUtils;

String result = StringUtils.join(list, ", ");

If you are fortunate enough to be using Java 8, then it's even easier...just use String.join

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

Solution 2 - Java

Using Java 8+

String str = list.stream().collect(Collectors.joining())

or even

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

Solution 3 - Java

Your approach is dependent on Java's ArrayList#toString() implementation.

While the implementation is documented in the Java API and very unlikely to change, there's a chance it could. It's far more reliable to implement this yourself (loops, StringBuilders, recursion whatever you like better).

Sure this approach may seem "neater" or more "too sweet" or "money" but it is, in my opinion, a worse approach.

Solution 4 - Java

A variation on codefin's answer

public static String concatStringsWSep(Iterable<String> strings, String separator) {
    StringBuilder sb = new StringBuilder();
    String sep = "";
    for(String s: strings) {
        sb.append(sep).append(s);
        sep = separator;
    }
    return sb.toString();                           
}

Solution 5 - Java

If you are developing for Android, there is TextUtils.join provided by the SDK.

Solution 6 - Java

This is the most elegant and clean way I've found so far:

list.stream().collect(Collectors.joining(delimiter));

Solution 7 - Java

Guava is a pretty neat library from Google:

Joiner joiner = Joiner.on(", ");
joiner.join(sList);

Solution 8 - Java

I prefer String.join(list) in Java 8

Solution 9 - Java

Have you seen this Coding Horror blog entry?

The Sad Tragedy of Micro-Optimization Theater

I am not shure whether or not it is "neater", but from a performance-standpoint it probably won't matter much.

Solution 10 - Java

ArrayList inherits its toString()-method from AbstractCollection, ie:

public String toString() {
    Iterator<E> i = iterator();
    if (! i.hasNext())
        return "[]";

    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (;;) {
        E e = i.next();
        sb.append(e == this ? "(this Collection)" : e);
        if (! i.hasNext())
            return sb.append(']').toString();
        sb.append(", ");
    }
}

Building the string yourself will be far more efficient.


If you really want to aggregate the strings beforehand in some sort of List, you should provide your own method to efficiently join them, e.g. like this:

static String join(Collection<?> items, String sep) {
    if(items.size() == 0)
        return "";

    String[] strings = new String[items.size()];
    int length = sep.length() * (items.size() - 1);

    int idx = 0;
    for(Object item : items) {
        String str = item.toString();
        strings[idx++] = str;
        length += str.length();
    }

    char[] chars = new char[length];
    int pos = 0;

    for(String str : strings) {
        str.getChars(0, str.length(), chars, pos);
        pos += str.length();

        if(pos < length) {
            sep.getChars(0, sep.length(), chars, pos);
            pos += sep.length();
        }
    }

    return new String(chars);
}

Solution 11 - Java

It seems to me that the StringBuilder will be quick and efficient.

The basic form would look something like this:

public static String concatStrings(List<String> strings)
{
	StringBuilder sb = new StringBuilder();
	for(String s: strings)
	{
		sb.append(s);
	}
	return sb.toString();		
}

If that's too simplistic (and it probably is), you can use a similar approach and add a separator like this:

	public static String concatStringsWSep(List<String> strings, String separator)
{
	StringBuilder sb = new StringBuilder();
	for(int i = 0; i < strings.size(); i++)
	{
		sb.append(strings.get(i));
		if(i < strings.size() - 1)
			sb.append(separator);
	}
	return sb.toString();				
}

I agree with the others who have responded to this question when they say that you should not rely on the toString() method of Java's ArrayList.

Solution 12 - Java

> I somehow found this to be neater than > using the StringBuilder/StringBuffer > approach.

I guess it depends on what approach you took.

The AbstractCollection#toString() method simply iterates over all the elements and appends them to a StringBuilder. So your method may be saving a few lines of code but at the cost of extra String manipulation. Whether that tradeoff is a good one is up to you.

Solution 13 - Java

Rather than depending on ArrayList.toString() implementation, you could write a one-liner, if you are using java 8:

String result = sList.stream()
                     .reduce("", String::concat);

If you prefer using StringBuffer instead of String since String::concat has a runtime of O(n^2), you could convert every String to StringBuffer first.

StringBuffer result = sList.stream()
                           .map(StringBuffer::new)
                           .reduce(new StringBuffer(""), StringBuffer::append);
     

Solution 14 - Java

Next variation on Peter Lawrey's answer without initialization of a new string every loop turn

String concatList(List<String> sList, String separator)
{
    Iterator<String> iter = sList.iterator();
    StringBuilder sb = new StringBuilder();

    while (iter.hasNext())
    {
        sb.append(iter.next()).append( iter.hasNext() ? separator : "");
    }
    return sb.toString();
}

Solution 15 - Java

Assuming it's faster to just move a pointer / set a byte to null (or however Java implements StringBuilder#setLength), rather than check a condition each time through the loop to see when to append the delimiter, you could use this method:

public static String Intersperse (Collection<?> collection, String delimiter)
{
StringBuilder sb = new StringBuilder ();
for (Object item : collection)
{
if (item == null) continue;
sb.append (item).append (delimiter);
}
sb.setLength (sb.length () - delimiter.length ());
return sb.toString ();
}

Solution 16 - Java

Depending on the need for performance and amount of elements to be added, this might be an ok solution. If the amount of elements are high, the Arraylists reallocation of memory might be a bit slower than StringBuilder.

Solution 17 - Java

Using the Functional Java library, import these:

import static fj.pre.Monoid.stringMonoid;
import static fj.data.List.list;
import fj.data.List;

... then you can do this:

List<String> ss = list("foo", "bar", "baz");
String s = stringMonoid.join(ss, ", ");

Or, the generic way, if you don't have a list of Strings:

public static <A> String showList(List<A> l, Show<A> s) {
  return stringMonoid.join(l.map(s.showS_()), ", ");
}

Solution 18 - Java

if you have json in your dependencies.you can use new JSONArray(list).toString()

Solution 19 - Java

In java 8 you can also use a reducer, something like:

public static String join(List<String> strings, String joinStr) {
	return strings.stream().reduce("", (prev, cur) -> prev += (cur + joinStr));
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJagmalView Question on Stackoverflow
Solution 1 - JavaJeff OlsonView Answer on Stackoverflow
Solution 2 - JavaAndrei NView Answer on Stackoverflow
Solution 3 - JavaJack LeowView Answer on Stackoverflow
Solution 4 - JavaPeter LawreyView Answer on Stackoverflow
Solution 5 - JavaChunliang LyuView Answer on Stackoverflow
Solution 6 - JavaAleksandar JovanovicView Answer on Stackoverflow
Solution 7 - JavaandrasView Answer on Stackoverflow
Solution 8 - JavaManish MulaniView Answer on Stackoverflow
Solution 9 - JavasdfxView Answer on Stackoverflow
Solution 10 - JavaChristophView Answer on Stackoverflow
Solution 11 - JavacodefinView Answer on Stackoverflow
Solution 12 - JavaKevinView Answer on Stackoverflow
Solution 13 - JavaSreekanthView Answer on Stackoverflow
Solution 14 - Javauser2979550View Answer on Stackoverflow
Solution 15 - JavaMonkeeSageView Answer on Stackoverflow
Solution 16 - JavageorgView Answer on Stackoverflow
Solution 17 - JavaApocalispView Answer on Stackoverflow
Solution 18 - Javaprogramer8View Answer on Stackoverflow
Solution 19 - Javatheol.zacharopoulosView Answer on Stackoverflow