The simplest way to comma-delimit a list?

JavaPretty Print

Java Problem Overview


What is the clearest way to comma-delimit a list in Java?

I know several ways of doing it, but I'm wondering what the best way is (where "best" means clearest and/or shortest, not the most efficient.

I have a list and I want to loop over it, printing each value. I want to print a comma between each item, but not after the last one (nor before the first one).

List --> Item ( , Item ) *
List --> ( Item , ) * Item

Sample solution 1:

boolean isFirst = true;
for (Item i : list) {
  if (isFirst) {
    System.out.print(i);        // no comma
    isFirst = false;
  } else {
    System.out.print(", "+i);   // comma
  }
}

Sample solution 2 - create a sublist:

if (list.size()>0) {
  System.out.print(list.get(0));   // no comma
  List theRest = list.subList(1, list.size());
  for (Item i : theRest) {
    System.out.print(", "+i);   // comma
  }
}

Sample solution 3:

  Iterator<Item> i = list.iterator();
  if (i.hasNext()) {
    System.out.print(i.next());
    while (i.hasNext())
      System.out.print(", "+i.next());
  }

These treat the first item specially; one could instead treat the last one specially.

Incidentally, here is how List toString is implemented (it's inherited from AbstractCollection), in Java 1.6:

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

It exits the loop early to avoid the comma after the last item. BTW: this is the first time I recall seeing "(this Collection)"; here's code to provoke it:

List l = new LinkedList();
l.add(l);
System.out.println(l);

I welcome any solution, even if they use unexpected libraries (regexp?); and also solutions in languages other than Java (e.g. I think Python/Ruby have an intersperse function - how is that implemented?).

Clarification: by libraries, I mean the standard Java libraries. For other libraries, I consider them with other languages, and interested to know how they're implemented.

EDIT toolkit mentioned a similar question: https://stackoverflow.com/questions/285523/last-iteration-of-for-loop-in-java

And another: https://stackoverflow.com/questions/156650/does-the-last-element-in-a-loop-deserve-a-separate-treatment

Java Solutions


Solution 1 - Java

Java 8 and later

Using StringJoiner class, and forEach method :

StringJoiner joiner = new StringJoiner(",");
list.forEach(item -> joiner.add(item.toString());
return joiner.toString();

Using Stream, and Collectors:

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

Java 7 and earlier

See also #285523

String delim = "";
for (Item i : list) {
    sb.append(delim).append(i);
    delim = ",";
}

Solution 2 - Java

org.apache.commons.lang3.StringUtils.join(list,",");

Solution 3 - Java

Java 8 provides several new ways to do this:

Example:

// Util method for strings and other char sequences
List<String> strs = Arrays.asList("1", "2", "3");
String listStr1 = String.join(",", strs);

// For any type using streams and collectors
List<Object> objs = Arrays.asList(1, 2, 3);
String listStr2 = objs.stream()
    .map(Object::toString)
    .collect(joining(",", "[", "]"));

// Using the new StringJoiner class
StringJoiner joiner = new StringJoiner(", ", "[", "]");
joiner.setEmptyValue("<empty>");
for (Integer i : objs) {
  joiner.add(i.toString());
}
String listStr3 = joiner.toString();

The approach using streams assumes import static java.util.stream.Collectors.joining;.

Solution 4 - Java

Joiner.on(",").join(myList)

Joiner.

Solution 5 - Java

If you use the Spring Framework you can do it with StringUtils:

public static String arrayToDelimitedString(Object[] arr)
public static String arrayToDelimitedString(Object[] arr, String delim)
public static String collectionToCommaDelimitedString(Collection coll)
public static String collectionToCommaDelimitedString(Collection coll, String delim)

Solution 6 - Java

Based on Java's List toString implementation:

Iterator i = list.iterator();
for (;;) {
  sb.append(i.next());
  if (! i.hasNext()) break;
  ab.append(", ");
}

It uses a grammar like this:

List --> (Item , )* Item

By being last-based instead of first-based, it can check for skip-comma with the same test to check for end-of-list. I think this one is very elegant, but I'm not sure about clarity.

Solution 7 - Java

There is a pretty way to achieve this using Java 8:

List<String> list = Arrays.asList(array);
String joinedString = String.join(",", list);

Solution 8 - Java

for(int i=0, length=list.size(); i<length; i++)
  result+=(i==0?"":", ") + list.get(i);

Solution 9 - Java

String delimiter = ",";
StringBuilder sb = new StringBuilder();
for (Item i : list) {
	sb.append(delimiter).append(i);
}
sb.toString().replaceFirst(delimiter, "");

Solution 10 - Java

One option for the foreach loop is:

StringBuilder sb = new StringBuilder();
for(String s:list){
  if (sb.length()>0) sb.append(",");
  sb.append(s);
}

Solution 11 - Java

StringBuffer result = new StringBuffer();
for(Iterator it=list.iterator; it.hasNext(); ) {
  if (result.length()>0)
    result.append(", ");
  result.append(it.next());
}

Update: As Dave Webb mentioned in the comments this may not produce correct results if the first items in the list are empty strings.

Solution 12 - Java

I usually do this :

StringBuffer sb = new StringBuffer();
Iterator it = myList.iterator();
if (it.hasNext()) { sb.append(it.next().toString()); }
while (it.hasNext()) { sb.append(",").append(it.next().toString()); }

Though I think I'll to a this check from now on as per the Java implementation ;)

Solution 13 - Java

If you can use Groovy (which runs on the JVM):

def list = ['a', 'b', 'c', 'd']
println list.join(',')

Solution 14 - Java

(Copy paste of my own answer from here.) Many of the solutions described here are a bit over the top, IMHO, especially those that rely on external libraries. There is a nice clean, clear idiom for achieving a comma separated list that I have always used. It relies on the conditional (?) operator:

Edit: Original solution correct, but non-optimal according to comments. Trying a second time:

int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
for (int i = 0 ;  i < array.length; i++)
       builder.append(i == 0 ? "" : ",").append(array[i]);

There you go, in 4 lines of code including the declaration of the array and the StringBuilder.

2nd Edit: If you are dealing with an Iterator:

    List<Integer> list = Arrays.asList(1, 2, 3);
    StringBuilder builder = new StringBuilder();
    for (Iterator it = list.iterator(); it.hasNext();)
        builder.append(it.next()).append(it.hasNext() ? "," : "");

Solution 15 - Java

I usually use something similar to version 3. It works well c/c++/bash/... :P

Solution 16 - Java

This is very short, very clear, but gives my sensibilities the creeping horrors. It's also a bit awkward to adapt to different delimiters, especially if a String (not char).

for (Item i : list)
  sb.append(',').append(i);
if (sb.charAt(0)==',') sb.deleteCharAt(0);

Inspired by: https://stackoverflow.com/questions/285523/last-iteration-of-for-loop-in-java/669221#669221

Solution 17 - Java

I didn't compile it... but should work (or be close to working).

public static <T> String toString(final List<T> list, 
                                  final String delim)
{
    final StringBuilder builder;
    
    builder = new StringBuilder();

    for(final T item : list)
    {
        builder.append(item);
        builder.append(delim);
    }
    
    // kill the last delim
    builder.setLength(builder.length() - delim.length());

    return (builder.toString());
}

Solution 18 - Java

StringBuffer sb = new StringBuffer();

for (int i = 0; i < myList.size(); i++)
{ 
    if (i > 0) 
    {
        sb.append(", ");
    }

    sb.append(myList.get(i)); 
}

Solution 19 - Java

I somewhat like this approach, which I found on a blog some time ago. Unfortunately I don't remember the blog's name/URL.

You can create a utility/helper class that looks like this:

private class Delimiter
{
    private final String delimiter;
    private boolean first = true;

    public Delimiter(String delimiter)
    {
        this.delimiter = delimiter;
    }

    @Override
    public String toString()
    {
        if (first) {
            first = false;
            return "";
        }

        return delimiter;
    }
}

Using the helper class is simple as this:

StringBuilder sb = new StringBuilder();
Delimiter delimiter = new Delimiter(", ");

for (String item : list) {
    sb.append(delimiter);
    sb.append(item);
}

Solution 20 - Java

I like this solution:

String delim = " - ", string = "";

for (String item : myCollection)
    string += delim + item;

string = string.substring(delim.length());

I assume it can make use of StringBuilder too.

Solution 21 - Java

Because your delimiter is ", " you could use any of the following:

public class StringDelim {
    
    public static void removeBrackets(String string) {
        System.out.println(string.substring(1, string.length() - 1));
    }
    
    public static void main(String... args) {
        // Array.toString() example
        String [] arr = {"Hi" , "My", "name", "is", "br3nt"};
        String string = Arrays.toString(arr);
        removeBrackets(string);
        
        // List#toString() example
        List<String> list = new ArrayList<String>();
        list.add("Hi");
        list.add("My");
        list.add("name");
        list.add("is");
        list.add("br3nt");
        string = list.toString();
        removeBrackets(string);
        
        // Map#values().toString() example
        Map<String, String> map = new LinkedHashMap<String, String>();
        map.put("1", "Hi");
        map.put("2", "My");
        map.put("3", "name");
        map.put("4", "is");
        map.put("5", "br3nt");
        System.out.println(map.values().toString());
        removeBrackets(string);
        
        // Enum#toString() example
        EnumSet<Days> set = EnumSet.allOf(Days.class);
        string = set.toString();
        removeBrackets(string);
    }
    
    public enum Days {
        MON("Monday"),
        TUE("Tuesday"),
        WED("Wednesday"),
        THU("Thursday"),
        FRI("Friday"),
        SAT("Saturday"),
        SUN("Sunday");

        private final String day;

        Days(String day) {this.day = day;}
        public String toString() {return this.day;}
    }
}

If your delimiter is ANYTHING else then this isn't going to work for you.

Solution 22 - Java

In my opinion, this is the simplest to read and understand:

StringBuilder sb = new StringBuilder();
for(String string : strings) {
	sb.append(string).append(',');
}
sb.setLength(sb.length() - 1);
String result = sb.toString();

Solution 23 - Java

In Python its easy

",".join( yourlist )

In C# there is a static method on the String class

String.Join(",", yourlistofstrings)

Sorry, not sure about Java but thought I'd pipe up as you asked about other languages. I'm sure there would be something similar in Java.

Solution 24 - Java

You can also unconditionally add the delimiter string, and after the loop remove the extra delimiter at the end. Then an "if list is empty then return this string" at the beginning will allow you to avoid the check at the end (as you cannot remove characters from an empty list)

So the question really is:

"Given a loop and an if, what do you think is the clearest way to have these together?"

Solution 25 - Java

if (array.length>0)          // edited in response Joachim's comment
  sb.append(array[i]);
for (int i=1; i<array.length; i++)
  sb.append(",").append(array[i]);

Based on https://stackoverflow.com/questions/668952/clearest-way-to-comma-delimit-a-list-java/669831#669831

Using this idea: https://stackoverflow.com/questions/156650/does-the-last-element-in-a-loop-deserve-a-separate-treatment

Solution 26 - Java

public static String join (List<String> list, String separator) {
  String listToString = "";

  if (list == null || list.isEmpty()) {
   return listToString;
  }

  for (String element : list) {
   listToString += element + separator;
  }

  listToString = listToString.substring(0, separator.length());

  return listToString;
}

Solution 27 - Java

public String toString(List<Item> items)
{
	StringBuilder sb = new StringBuilder("[");
	
	for (Item item : items)
	{
		sb.append(item).append(", ");
	}
	
	if (sb.length() >= 2)
	{
		//looks cleaner in C# sb.Length -= 2;
		sb.setLength(sb.length() - 2);
	}
	
	sb.append("]");
	
	return sb.toString();
}

Solution 28 - Java

None of the answers uses recursion so far...

public class Main {

    public static String toString(List<String> list, char d) {
        int n = list.size();
        if(n==0) return "";
        return n > 1 ? Main.toString(list.subList(0, n - 1), d) + d
                  + list.get(n - 1) : list.get(0);
    }
    
    public static void main(String[] args) {
        List<String> list = Arrays.asList(new String[]{"1","2","3"});
        System.out.println(Main.toString(list, ','));
    }

}

Solution 29 - Java

private String betweenComma(ArrayList<String> strings) {
	String united = "";
	for (String string : strings) {
		united = united + "," + string;
	}
	return united.replaceFirst(",", "");
}

Solution 30 - Java

Method

String join(List<Object> collection, String delimiter){
    StringBuilder stringBuilder = new StringBuilder();
    int size = collection.size();
    for (Object value : collection) {
        size --;
        if(size > 0){
            stringBuilder.append(value).append(delimiter);
        }
    }

    return stringBuilder.toString();
}

Usage

Given the array of [1,2,3]

join(myArray, ",") // 1,2,3

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
Question13renView Question on Stackoverflow
Solution 1 - JavatoolkitView Answer on Stackoverflow
Solution 2 - JavatrunkcView Answer on Stackoverflow
Solution 3 - JavaLiiView Answer on Stackoverflow
Solution 4 - JavaStefan KendallView Answer on Stackoverflow
Solution 5 - JavaHenryk KonsekView Answer on Stackoverflow
Solution 6 - Java13renView Answer on Stackoverflow
Solution 7 - JavaKrishnanunni P VView Answer on Stackoverflow
Solution 8 - JavacherouvimView Answer on Stackoverflow
Solution 9 - JavaAlfredo OsorioView Answer on Stackoverflow
Solution 10 - JavaBAHView Answer on Stackoverflow
Solution 11 - JavacherouvimView Answer on Stackoverflow
Solution 12 - JavaAlex MarshallView Answer on Stackoverflow
Solution 13 - JavakungfooView Answer on Stackoverflow
Solution 14 - JavaJulien ChastangView Answer on Stackoverflow
Solution 15 - JavasfossenView Answer on Stackoverflow
Solution 16 - Java13renView Answer on Stackoverflow
Solution 17 - JavaTofuBeerView Answer on Stackoverflow
Solution 18 - JavaAries McRaeView Answer on Stackoverflow
Solution 19 - JavaTobias MüllerView Answer on Stackoverflow
Solution 20 - Javabr3ntView Answer on Stackoverflow
Solution 21 - Javabr3ntView Answer on Stackoverflow
Solution 22 - JavaSergeyBView Answer on Stackoverflow
Solution 23 - JavatarnView Answer on Stackoverflow
Solution 24 - JavaThorbjørn Ravn AndersenView Answer on Stackoverflow
Solution 25 - Java13renView Answer on Stackoverflow
Solution 26 - Javauser441737View Answer on Stackoverflow
Solution 27 - JavaEblisView Answer on Stackoverflow
Solution 28 - JavalangsweirdtView Answer on Stackoverflow
Solution 29 - JavaSamet ÖZTOPRAKView Answer on Stackoverflow
Solution 30 - JavaIlya GazmanView Answer on Stackoverflow