271

I want to join a String[] with a glue string. Is there a function for this?

2

24 Answers 24

319

Starting from Java8 it is possible to use String.join().

String.join(", ", new String[]{"Hello", "World", "!"})

Generates:

Hello, World, !

Otherwise, Apache Commons Lang has a StringUtils class which has a join function which will join arrays together to make a String.

For example:

StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")

Generates the following String:

Hello, World, !
Sign up to request clarification or add additional context in comments.

7 Comments

For the benefit of people searching for this answer, it should probably be noted that this is also the equivalent of a Perl join.
it says it's undefined for me
@Ninjaxor 1. commons-lang*jar must be in classpath 2. import org.apache.commons.lang3.StringUtils;
I would recommend you edit this answer to append a reference to the new String.join() method introduced in Java 8. This way, the huge numbers of people reading this accepted answer will benefit from that knowledge. Currently, the highest voted answer mentioning this fact is rather lost down below...
It's worth mentioning that String.join() would work only for List<CharSequence> or CharSequence[] elements.
|
73

If you were looking for what to use in android, it is:

String android.text.TextUtils.join(CharSequence delimiter, Object[] tokens)

for example:

String joined = TextUtils.join(";", MyStringArray);

2 Comments

This is clearly the best answer for all Android versions, as Java 8 is only coming out on Android in a bit. This solution uses the built in Android libs, rather than these silly "include a huge lib to perform one action" solutions.
It's September 2017, Java 8 for Android is still far away. Thanks for this answer!
60

In Java 8 you can use

1) Stream API :

String[] a = new String[] {"a", "b", "c"};
String result = Arrays.stream(a).collect(Collectors.joining(", "));

2) new String.join method: https://stackoverflow.com/a/21756398/466677

3) java.util.StringJoiner class: http://docs.oracle.com/javase/8/docs/api/java/util/StringJoiner.html

Comments

53

You could easily write such a function in about ten lines of code:

String combine(String[] s, String glue)
{
  int k = s.length;
  if ( k == 0 )
  {
    return null;
  }
  StringBuilder out = new StringBuilder();
  out.append( s[0] );
  for ( int x=1; x < k; ++x )
  {
    out.append(glue).append(s[x]);
  }
  return out.toString();
}

20 Comments

Good practice according to you...there is no universal standard for such things.
But if I included braces, that would have added two more lines of code, and I couldn't have claimed to have done it in 11 lines!
the problem is when you after a while, or someone else, in a hurry, add another line to that if/for without adding braces; or delete return null after if(k==0), whih in some cases would compiles but will be incorrect. Then it's better to sacrifice one extra line for that closing brace (the opening can stay in the same if/for line).
I think it's awesome that while most languages pack such functionality into their core, the Java community encourages everyone to reinvent the wheel.
11 lines? Bah! I can do it in 1! Simply remove all the newline characters in the source file.
|
27

A little mod instead of using substring():

//join(String array,delimiter)
public static String join(String r[],String d)
{
        if (r.length == 0) return "";
        StringBuilder sb = new StringBuilder();
        int i;
        for(i=0;i<r.length-1;i++){
            sb.append(r[i]);
            sb.append(d);
        }
        sb.append(r[i]);
        return sb.toString();
}

2 Comments

Voted up because you don't need to add any library.
Line 7: Is it be better if used .append() twice for each String instead of concatenate them and then append to the builder.
18

As with many questions lately, Java 8 to the rescue:


Java 8 added a new static method to java.lang.String which does exactly what you want:

public static String join(CharSequence delimeter, CharSequence... elements);

Using it:

String s = String.join(", ", new String[] {"Hello", "World", "!"});

Results in:

"Hello, World, !"

Comments

14

Google guava's library also has this kind of capability. You can see the String[] example also from the API.

As already described in the api, beware of the immutability of the builder methods.

It can accept an array of objects so it'll work in your case. In my previous experience, i tried joining a Stack which is an iterable and it works fine.

Sample from me :

Deque<String> nameStack = new ArrayDeque<>();
nameStack.push("a coder");
nameStack.push("i am");
System.out.println("|" + Joiner.on(' ').skipNulls().join(nameStack) + "|");

prints out : |i am a coder|

Comments

9

Given:

String[] a = new String[] { "Hello", "World", "!" };

Then as an alternative to coobird's answer, where the glue is ", ":

Arrays.asList(a).toString().replaceAll("^\\[|\\]$", "")

Or to concatenate with a different string, such as " &amp; ".

Arrays.asList(a).toString().replaceAll(", ", " &amp; ").replaceAll("^\\[|\\]$", "")

However... this one ONLY works if you know that the values in the array or list DO NOT contain the character string ", ".

1 Comment

Arrays.asList(a).toString() worked for what I wanted to do
9

If you are using the Spring Framework then you have the StringUtils class:

import static org.springframework.util.StringUtils.arrayToDelimitedString;

arrayToDelimitedString(new String[] {"A", "B", "C"}, "\n");

Comments

8

Not in core, no. A search for "java array join string glue" will give you some code snippets on how to achieve this though.

e.g.

public static String join(Collection s, String delimiter) {
    StringBuffer buffer = new StringBuffer();
    Iterator iter = s.iterator();
    while (iter.hasNext()) {
        buffer.append(iter.next());
        if (iter.hasNext()) {
            buffer.append(delimiter);
        }
    }
    return buffer.toString();
}

2 Comments

Use StringBuilder (non-thread-safe) in place of StringBuffer (thread-safe) for better performance. The interface is the same.
This seems to be from snippets.dzone.com/posts/show/91. The comments suggest a much improved version: public static String join( Iterable< ? extends Object > pColl, String separator ) { Iterator< ? extends Object > oIter; if ( pColl == null || ( !( oIter = pColl.iterator() ).hasNext() ) ) return ""; StringBuilder oBuilder = new StringBuilder( String.valueOf( oIter.next() ) ); while ( oIter.hasNext() ) oBuilder.append( separator ).append( oIter.next() ); return oBuilder.toString(); }
6

If you've landed here looking for a quick array-to-string conversion, try Arrays.toString().

Creates a String representation of the Object[] passed. The result is surrounded by brackets ("[]"), each element is converted to a String via the String.valueOf(Object) and separated by ", ". If the array is null, then "null" is returned.

1 Comment

THANKS VERY MUCH! The strings are separated by ", " and the whole thing has "[]" around it, which is fine with me.
5

Just for the "I've the shortest one" challenge, here are mines ;)

Iterative:

public static String join(String s, Object... a) {
    StringBuilder o = new StringBuilder();
    for (Iterator<Object> i = Arrays.asList(a).iterator(); i.hasNext();)
        o.append(i.next()).append(i.hasNext() ? s : "");
    return o.toString();
}

Recursive:

public static String join(String s, Object... a) {
    return a.length == 0 ? "" : a[0] + (a.length == 1 ? "" : s + join(s, Arrays.copyOfRange(a, 1, a.length)));
}

2 Comments

The recursive version is elegant. Definitely going to use that.
The recursive version may be elegant, but inefficient for large arrays ("copyOfRange()").
4

Nothing built-in that I know of.

Apache Commons Lang has a class called StringUtils which contains many join functions.

Comments

4

This is how I do it.

private String join(String[] input, String delimiter)
{
    StringBuilder sb = new StringBuilder();
    for(String value : input)
    {
        sb.append(value);
        sb.append(delimiter);
    }
    int length = sb.length();
    if(length > 0)
    {
        // Remove the extra delimiter
        sb.setLength(length - delimiter.length());
    }
    return sb.toString();
}

Comments

2

A similar alternative

/**
 * @param delimiter 
 * @param inStr
 * @return String
 */
public static String join(String delimiter, String... inStr)
{
    StringBuilder sb = new StringBuilder();
    if (inStr.length > 0)
    {
        sb.append(inStr[0]);
        for (int i = 1; i < inStr.length; i++)
        {
            sb.append(delimiter);                   
            sb.append(inStr[i]);
        }
    }
    return sb.toString();
}

Comments

2

My spin.

public static String join(Object[] objects, String delimiter) {
  if (objects.length == 0) {
    return "";
  }
  int capacityGuess = (objects.length * objects[0].toString().length())
      + ((objects.length - 1) * delimiter.length());
  StringBuilder ret = new StringBuilder(capacityGuess);
  ret.append(objects[0]);
  for (int i = 1; i < objects.length; i++) {
    ret.append(delimiter);
    ret.append(objects[i]);
  }
  return ret.toString();
}

public static String join(Object... objects) {
  return join(objects, "");
}

Comments

1

Do you like my 3-lines way using only String class's methods?

static String join(String glue, String[] array) {
    String line = "";
    for (String s : array) line += s + glue;
    return (array.length == 0) ? line : line.substring(0, line.length() - glue.length());
}

1 Comment

It's not meant to be efficient. Use StringBuilder if you need efficiency :P
0

To get "str1, str2" from "str1", "str2", "" :

Stream.of("str1", "str2", "").filter(str -> !str.isEmpty()).collect(Collectors.joining(", ")); 

Also you can add extra null-check

Comments

0

In case you're using Functional Java library and for some reason can't use Streams from Java 8 (which might be the case when using Android + Retrolambda plugin), here is a functional solution for you:

String joinWithSeparator(List<String> items, String separator) {
    return items
            .bind(id -> list(separator, id))
            .drop(1)
            .foldLeft(
                    (result, item) -> result + item,
                    ""
            );
}

Note that it's not the most efficient approach, but it does work good for small lists.

Comments

0

Whatever approach you choose, be aware of null values in the array. Their string representation is "null" so if it is not your desired behavior, skip null elements.

String[] parts = {"Hello", "World", null, "!"};
Stream.of(parts)
      .filter(Objects::nonNull)
      .collect(Collectors.joining(" "));

Comments

0

As already mentioned, class StringJoiner is also an available option since Java 8:

@NotNull
String stringArrayToCsv(@NotNull String[] data) {
    if (data.length == 0) {return "";}
    StringJoiner joiner = new StringJoiner(", ");
    Iterator<String> itr = Arrays.stream(data).iterator();
    while (itr.hasNext()) {joiner.add(itr.next());}
    return joiner.toString();
}

However, the traditional String.join() is less imports and less code:

@NotNull
String stringArrayToCsv(@NotNull String[] data) {
    if (data.length == 0) {return "";}
    return String.join(", ", data);
}

Comments

-1

I do it this way using a StringBuilder:

public static String join(String[] source, String delimiter) {
    if ((null == source) || (source.length < 1)) {
        return "";
    }

    StringBuilder stringbuilder = new StringBuilder();
    for (String s : source) {
        stringbuilder.append(s + delimiter);
    }
    return stringbuilder.toString();
} // join((String[], String)

2 Comments

s + delimiter (string concatenation with the plus operator) defeats the whole purpose of using a StringBuilder.
Plus, this approach would mean that an array like: {"foo", "bar"} with delimiter ":" would be turned into "foo:bar:"
-2

There is simple shorthand technique I use most of the times..

String op = new String;
for (int i : is) 
{
    op += candidatesArr[i-1]+",";
}
op = op.substring(0, op.length()-1);

3 Comments

This only works with delimiters of length 1 and requires 'magic numbers' (though quite local) if you wanted a delimiter of a different length.
You may add multiple characters while appending
than simply do: op = op.substring(0, op.length() - ",".length()); whats the big deal?
-3

java.util.Arrays has an 'asList' method. Together with the java.util.List/ArrayList API this gives you all you need:;

private static String[] join(String[] array1, String[] array2) {

    List<String> list = new ArrayList<String>(Arrays.asList(array1));
    list.addAll(Arrays.asList(array2));
    return list.toArray(new String[0]);
}

1 Comment

The question is how to join an array of string with a delimiter, not how to join two arrays of strings together.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.