Java: convert List<String> to a join()d String

JavaStringList

Java Problem Overview


JavaScript has Array.join()

js>["Bill","Bob","Steve"].join(" and ")
Bill and Bob and Steve

Does Java have anything like this? I know I can cobble something up myself with StringBuilder:

static public String join(List<String> list, String conjunction)
{
   StringBuilder sb = new StringBuilder();
   boolean first = true;
   for (String item : list)
   {
      if (first)
         first = false;
      else
         sb.append(conjunction);
      sb.append(item);
   }
   return sb.toString();
}

.. but there's no point in doing this if something like it is already part of the JDK.

Java Solutions


Solution 1 - Java

With Java 8 you can do this without any third party library.

If you want to join a Collection of Strings you can use the new String.join() method:

List<String> list = Arrays.asList("foo", "bar", "baz");
String joined = String.join(" and ", list); // "foo and bar and baz"

If you have a Collection with another type than String you can use the Stream API with the joining Collector:

List<Person> list = Arrays.asList(
  new Person("John", "Smith"),
  new Person("Anna", "Martinez"),
  new Person("Paul", "Watson ")
);

String joinedFirstNames = list.stream()
  .map(Person::getFirstName)
  .collect(Collectors.joining(", ")); // "John, Anna, Paul"

The StringJoiner class may also be useful.

Solution 2 - Java

All the references to Apache Commons are fine (and that is what most people use) but I think the Guava equivalent, Joiner, has a much nicer API.

You can do the simple join case with

Joiner.on(" and ").join(names)

but also easily deal with nulls:

Joiner.on(" and ").skipNulls().join(names);

or

Joiner.on(" and ").useForNull("[unknown]").join(names);

and (useful enough as far as I'm concerned to use it in preference to commons-lang), the ability to deal with Maps:

Map<String, Integer> ages = .....;
String foo = Joiner.on(", ").withKeyValueSeparator(" is ").join(ages);
// Outputs:
// Bill is 25, Joe is 30, Betty is 35

which is extremely useful for debugging etc.

Solution 3 - Java

Not out of the box, but many libraries have similar:

Commons Lang:

org.apache.commons.lang.StringUtils.join(list, conjunction);

Spring:

org.springframework.util.StringUtils.collectionToDelimitedString(list, conjunction);

Solution 4 - Java

On Android you could use TextUtils class.

TextUtils.join(" and ", names);

Solution 5 - Java

No, there's no such convenience method in the standard Java API.

Not surprisingly, Apache Commons provides such a thing in their StringUtils class in case you don't want to write it yourself.

Solution 6 - Java

Three possibilities in Java 8:

List<String> list = Arrays.asList("Alice", "Bob", "Charlie")

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

result = list.stream().collect(Collectors.joining(" and "));

result = list.stream().reduce((t, u) -> t + " and " + u).orElse("");

Solution 7 - Java

With a java 8 collector, this can be done with the following code:

Arrays.asList("Bill", "Bob", "Steve").stream()
.collect(Collectors.joining(" and "));

Also, the simplest solution in java 8:

String.join(" and ", "Bill", "Bob", "Steve");

or

String.join(" and ", Arrays.asList("Bill", "Bob", "Steve"));

Solution 8 - Java

I wrote this one (I use it for beans and exploit toString, so don't write Collection<String>):

public static String join(Collection<?> col, String delim) {
    StringBuilder sb = new StringBuilder();
    Iterator<?> iter = col.iterator();
    if (iter.hasNext())
        sb.append(iter.next().toString());
    while (iter.hasNext()) {
        sb.append(delim);
        sb.append(iter.next().toString());
    }
    return sb.toString();
}

but Collection isn't supported by JSP, so for TLD I wrote:

public static String join(List<?> list, String delim) {
    int len = list.size();
    if (len == 0)
        return "";
    StringBuilder sb = new StringBuilder(list.get(0).toString());
    for (int i = 1; i < len; i++) {
        sb.append(delim);
        sb.append(list.get(i).toString());
    }
    return sb.toString();
}

and put to .tld file:

<?xml version="1.0" encoding="UTF-8"?>
<taglib version="2.1" xmlns="http://java.sun.com/xml/ns/javaee"
    <function>
        <name>join</name>
        <function-class>com.core.util.ReportUtil</function-class>
        <function-signature>java.lang.String join(java.util.List, java.lang.String)</function-signature>
    </function>
</taglib>

and use it in JSP files as:

<%@taglib prefix="funnyFmt" uri="tag:com.core.util,2013:funnyFmt"%>
${funnyFmt:join(books, ", ")}

Solution 9 - Java

Code you have is right way to do it if you want to do using JDK without any external libraries. There is no simple "one-liner" that you could use in JDK.

If you can use external libs, I recommend that you look into http://commons.apache.org/lang/api/org/apache/commons/lang/StringUtils.html">org.apache.commons.lang.StringUtils</a> class in Apache Commons library.

An example of usage:

List<String> list = Arrays.asList("Bill", "Bob", "Steve");
String joinedResult = StringUtils.join(list, " and ");

Solution 10 - Java

An orthodox way to achieve it, is by defining a new function:

public static String join(String joinStr, String... strings) {
	if (strings == null || strings.length == 0) {
		return "";
	} else if (strings.length == 1) {
		return strings[0];
	} else {
		StringBuilder sb = new StringBuilder(strings.length * 1 + strings[0].length());
		sb.append(strings[0]);
		for (int i = 1; i < strings.length; i++) {
			sb.append(joinStr).append(strings[i]);
		}
		return sb.toString();
	}
}

Sample:

String[] array = new String[] { "7, 7, 7", "Bill", "Bob", "Steve",
		"[Bill]", "1,2,3", "Apple ][","~,~" };

String joined;
joined = join(" and ","7, 7, 7", "Bill", "Bob", "Steve", "[Bill]", "1,2,3", "Apple ][","~,~");
joined = join(" and ", array); // same result

System.out.println(joined);

Output: > 7, 7, 7 and Bill and Bob and Steve and [Bill] and 1,2,3 and Apple ][ and ,

Solution 11 - Java

Java 8 solution with java.util.StringJoiner

Java 8 has got a StringJoiner class. But you still need to write a bit of boilerplate, because it's Java.

StringJoiner sj = new StringJoiner(" and ", "" , "");
String[] names = {"Bill", "Bob", "Steve"};
for (String name : names) {
   sj.add(name);
}
System.out.println(sj);

Solution 12 - Java

You can use the apache commons library which has a StringUtils class and a join method.

Check this link: https://commons.apache.org/proper/commons-lang/javadocs/api.2.0/org/apache/commons/lang/StringUtils.html

Note that the link above may become obsolete over time, in which case you can just search the web for "apache commons StringUtils", which should allow you to find the latest reference.

(referenced from this thread) https://stackoverflow.com/questions/187676/string-operations-in-java

Solution 13 - Java

You can do this:

String aToString = java.util.Arrays.toString(anArray);
// Do not need to do this if you are OK with '[' and ']'
aToString = aToString.substring(1, aToString.length() - 1);

Or a one-liner (only when you do not want '[' and ']')

String aToString = java.util.Arrays.toString(anArray).substring(1).replaceAll("\]$", "");

Hope this helps.

Solution 14 - Java

With java 1.8 stream can be used ,

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

List<String> list = Arrays.asList("Bill","Bob","Steve").
String str = list.stream().collect(Collectors.joining(" and "));

Solution 15 - Java

A fun way to do it with pure JDK, in one duty line:

String[] array = new String[] { "Bill", "Bob", "Steve","[Bill]","1,2,3","Apple ][" };
String join = " and ";
	
String joined = Arrays.toString(array).replaceAll(", ", join)
		.replaceAll("(^\\[)|(\\]$)", "");
	
System.out.println(joined);

Output:

> Bill and Bob and Steve and [Bill] and 1,2,3 and Apple ][


A not too perfect & not too fun way!

String[] array = new String[] { "7, 7, 7","Bill", "Bob", "Steve", "[Bill]",
		"1,2,3", "Apple ][" };
String join = " and ";

for (int i = 0; i < array.length; i++) array[i] = array[i].replaceAll(", ", "~,~");
String joined = Arrays.toString(array).replaceAll(", ", join)
		.replaceAll("(^\\[)|(\\]$)", "").replaceAll("~,~", ", ");

System.out.println(joined);

Output: > 7, 7, 7 and Bill and Bob and Steve and [Bill] and 1,2,3 and Apple ][

Solution 16 - Java

You might want to try Apache Commons StringUtils join method:

http://commons.apache.org/lang/api/org/apache/commons/lang/StringUtils.html#join(java.util.Iterator, java.lang.String)

I've found that Apache StringUtils picks up jdk's slack ;-)

Solution 17 - Java

EDIT

I also notice the toString() underlying implementation issue, and about the element containing the separator but I thought I was being paranoid.

Since I've got two comments on that regard, I'm changing my answer to:

static String join( List<String> list , String replacement  ) {
    StringBuilder b = new StringBuilder();
    for( String item: list ) { 
        b.append( replacement ).append( item );
    }
    return b.toString().substring( replacement.length() );
}

Which looks pretty similar to the original question.

So if you don't feel like adding the whole jar to your project you may use this.

I think there's nothing wrong with your original code. Actually, the alternative that everyone's is suggesting looks almost the same ( although it does a number of additional validations )

Here it is, along with the Apache 2.0 license.

public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer
    if (iterator == null) {
        return null;
    }
    if (!iterator.hasNext()) {
        return EMPTY;
    }
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }

    // two or more elements
    StringBuffer buf = new StringBuffer(256); // Java default is 16, probably too small
    if (first != null) {
        buf.append(first);
    }

    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

Now we know, thank you open source

Solution 18 - Java

If you're using Eclipse Collections (formerly GS Collections), you can use the makeString() method.

List<String> list = Arrays.asList("Bill", "Bob", "Steve");

String string = ListAdapter.adapt(list).makeString(" and ");

Assert.assertEquals("Bill and Bob and Steve", string);

If you can convert your List to an Eclipse Collections type, then you can get rid of the adapter.

MutableList<String> list = Lists.mutable.with("Bill", "Bob", "Steve");
String string = list.makeString(" and ");

If you just want a comma separated string, you can use the version of makeString() that takes no parameters.

Assert.assertEquals(
    "Bill, Bob, Steve", 
    Lists.mutable.with("Bill", "Bob", "Steve").makeString());

Note: I am a committer for Eclipse Collections.

Solution 19 - Java

Google's Guava API also has .join(), although (as should be obvious with the other replies), Apache Commons is pretty much the standard here.

Solution 20 - Java

Java 8 does bring the

Collectors.joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

method, that is nullsafe by using prefix + suffix for null values.

It can be used in the following manner:

String s = stringList.stream().collect(Collectors.joining(" and ", "prefix_", "_suffix"))

The Collectors.joining(CharSequence delimiter) method just calls joining(delimiter, "", "") internally.

Solution 21 - Java

You can use this from Spring Framework's StringUtils. I know it's already been mentioned, but you can actually just take this code and it works immediately, without needing Spring for it.

// from https://github.com/spring-projects/spring-framework/blob/master/spring-core/src/main/java/org/springframework/util/StringUtils.java

/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class StringUtils {
    public static String collectionToDelimitedString(Collection<?> coll, String delim, String prefix, String suffix) {
        if(coll == null || coll.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Iterator<?> it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext()) {
                sb.append(delim);
            }
        }
        return sb.toString();
    }
}

Solution 22 - Java

Another solution, it is a variation of another answer

public static String concatStringsWSep(Iterable<String> strings, String separator) {
    Iterator<String> it = strings.iterator();
    if( !it.hasNext() ) return "";
    StringBuilder sb = new StringBuilder(it.next());
    while( it.hasNext()) {
        sb.append(separator).append(it.next());
    }
    return sb.toString();                           
}

Solution 23 - Java

Try this:

java.util.Arrays.toString(anArray).replaceAll(", ", ",")
                .replaceFirst("^\\[","").replaceFirst("\\]$","");

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
QuestionJason SView Question on Stackoverflow
Solution 1 - JavamichaView Answer on Stackoverflow
Solution 2 - JavaCowanView Answer on Stackoverflow
Solution 3 - JavaArne BurmeisterView Answer on Stackoverflow
Solution 4 - JavaRafal EndenView Answer on Stackoverflow
Solution 5 - JavaBart KiersView Answer on Stackoverflow
Solution 6 - JavaamraView Answer on Stackoverflow
Solution 7 - JavaaifaView Answer on Stackoverflow
Solution 8 - JavagavenkoaView Answer on Stackoverflow
Solution 9 - JavaJuha SyrjäläView Answer on Stackoverflow
Solution 10 - JavaDaniel De LeónView Answer on Stackoverflow
Solution 11 - Javaklingt.netView Answer on Stackoverflow
Solution 12 - JavadcpView Answer on Stackoverflow
Solution 13 - JavaNawaManView Answer on Stackoverflow
Solution 14 - JavaSaurabhView Answer on Stackoverflow
Solution 15 - JavaDaniel De LeónView Answer on Stackoverflow
Solution 16 - JavaUpgradingdaveView Answer on Stackoverflow
Solution 17 - JavaOscarRyzView Answer on Stackoverflow
Solution 18 - JavaCraig P. MotlinView Answer on Stackoverflow
Solution 19 - JavaDean JView Answer on Stackoverflow
Solution 20 - JavathgView Answer on Stackoverflow
Solution 21 - JavaEpicPandaForceView Answer on Stackoverflow
Solution 22 - JavayasView Answer on Stackoverflow
Solution 23 - JavajorgeView Answer on Stackoverflow