[java] A method to reverse effect of java String.split()?

I am looking for a method to combine an array of strings into a delimited String. An opposite to split().

Wanted to ask the forum before I try writing my own (since the JDK has everything)

This question is related to java string split

The answer is


I like this better:

public String join(Collection<String> strCollection, String delimiter) {
    String joined = "";
    int noOfItems = 0;
    for (String item : strCollection) {
        joined += item;
        if (++noOfItems < strCollection.size())
            joined += delimiter;
    }
    return joined;
}

It is the neatest solution I have found so far. (Don't worry about the use of raw String objects instead of StringBuilder. Modern Java compilers use StringBuilder anyway, but this code is more readable).


For the sake of completeness, I'd like to add that you cannot reverse String#split in general, as it accepts a regular expression.

"hello__world".split("_+"); Yields ["hello", "world"].
"hello_world".split("_+"); Yields ["hello", "world"].

These yield identical results from a different starting point. splitting is not a one-to-one operation, and is thus non-reversible.

This all being said, if you assume your parameter to be a fixed string, not regex, then you can certainly do this using one of the many posted answers.


There has been an open feature request since at least 2009. The long and short of it is that it will part of the functionality of JDK 8's java.util.StringJoiner class. http://download.java.net/lambda/b81/docs/api/java/util/StringJoiner.html

Here is the Oracle issue if you are interested. http://bugs.sun.com/view_bug.do?bug_id=5015163

Here is an example of the new JDK 8 StringJoiner on an array of String

String[] a = new String[]{"first","second","third"};
StringJoiner sj = new StringJoiner(",");
for(String s:a) sj.add(s);
System.out.println(sj); //first,second,third

A utility method in String makes this even simpler:

String s = String.join(",", stringArray);

If you have an int[], Arrays.toString() is the easiest way.


For Android: in android.text.TextUtils there are methods:

public static String join (CharSequence delimiter, Iterable tokens)
public static String join (CharSequence delimiter, Object[] tokens)

Returns a string containing the tokens joined by delimiters.

tokens -- an array objects to be joined. Strings will be formed from the objects by calling object.toString().


I wrote this one:

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

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

Below code gives a basic idea. This is not best solution though.

public static String splitJoin(String sourceStr, String delim,boolean trim,boolean ignoreEmpty){
    return join(Arrays.asList(sourceStr.split(delim)), delim, ignoreEmpty);
}


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

There's no method in the JDK for this that I'm aware of. Apache Commons Lang has various overloaded join() methods in the StringUtils class that do what you want.


This one is not bad too :

public static String join(String delimitor,String ... subkeys) {
    String result = null;
    if(null!=subkeys && subkeys.length>0) {
        StringBuffer joinBuffer = new StringBuffer(subkeys[0]);
        for(int idx=1;idx<subkeys.length;idx++) {
            joinBuffer.append(delimitor).append(subkeys[idx]);
        }
        result = joinBuffer.toString();
    }
    return result;
}

Since JDK8 I love Streams and Lambdas a lot, so I would suggest:

public static String join( String delimiter, String[] array )
{
    return Arrays.asList( array ).stream().collect( Collectors.joining( delimiter ) );
}

You can sneak this functionality out of the Arrays utility package.

import java.util.Arrays;
...
    String delim = ":",
            csv_record = "Field0:Field1:Field2",
            fields[] = csv_record.split(delim);

    String rebuilt_record = Arrays.toString(fields)
            .replace(", ", delim)
            .replaceAll("[\\[\\]]", "");

If you use jdk8 see @Nathaniel Johnson's answer as that is better.

I think that many of the answer here are complex or not easily read. With branch prediction so efficient why you simply not use a if statement?

public static String join(List<String> fooList){

    if (fooList.isEmpty()) return "";

    StringBuilder sb = null;

    for (String element : fooList) {

        if (sb == null) {
            sb = new StringBuilder();
        } else {
            sb.append(", ");
        }

        sb.append(element);
    }
    return sb.toString();
}

Something that should be mentioned is that Apache uses a simple for loop with an if statement inside it like this (it uses an array as its index to know the first element), and openjdk 8 does the same but in separated methods calls instead of a simple loop.


Google also provides a joiner class in their Google Collections library:

Joiner API

Google Collections


I got the following example here

/*
7) Join Strings using separator >>>AB$#$CD$#$EF

 */

import org.apache.commons.lang.StringUtils;

public class StringUtilsTrial {
  public static void main(String[] args) {

    // Join all Strings in the Array into a Single String, separated by $#$
    System.out.println("7) Join Strings using separator >>>"
        + StringUtils.join(new String[] { "AB", "CD", "EF" }, "$#$"));
  }
}

There are several examples on DZone Snippets if you want to roll your own that works with a Collection. For example:

public static String join(AbstractCollection<String> s, String delimiter) {
    if (s == null || s.isEmpty()) return "";
    Iterator<String> iter = s.iterator();
    StringBuilder builder = new StringBuilder(iter.next());
    while( iter.hasNext() )
    {
        builder.append(delimiter).append(iter.next());
    }
    return builder.toString();
}

Based on all the previous answers:

public static String join(Iterable<? extends Object> elements, CharSequence separator) 
{
    StringBuilder builder = new StringBuilder();

    if (elements != null)
    {
        Iterator<? extends Object> iter = elements.iterator();
        if(iter.hasNext())
        {
            builder.append( String.valueOf( iter.next() ) );
            while(iter.hasNext())
            {
                builder
                    .append( separator )
                    .append( String.valueOf( iter.next() ) );
            }
        }
    }

    return builder.toString();
}

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 string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to split

Parameter "stratify" from method "train_test_split" (scikit Learn) Pandas split DataFrame by column value How to split large text file in windows? Attribute Error: 'list' object has no attribute 'split' Split function in oracle to comma separated values with automatic sequence How would I get everything before a : in a string Python Split String by delimiter position using oracle SQL JavaScript split String with white space Split a String into an array in Swift? Split pandas dataframe in two if it has more than 10 rows