The approach that I've taken has evolved since Java 1.0 to provide readability and maintain reasonable options for backward-compatibility with older Java versions, while also providing method signatures that are drop-in replacements for those from apache commons-lang. For performance reasons, I can see some possible objections to the use of Arrays.asList but I prefer helper methods that have sensible defaults without duplicating the one method that performs the actual work. This approach provides appropriate entry points to a reliable method that does not require array/list conversions prior to calling.
Possible variations for Java version compatibility include substituting StringBuffer (Java 1.0) for StringBuilder (Java 1.5), switching out the Java 1.5 iterator and removing the generic wildcard (Java 1.5) from the Collection (Java 1.2). If you want to take backward compatibility a step or two further, delete the methods that use Collection and move the logic into the array-based method.
public static String join(String[] values)
{
return join(values, ',');
}
public static String join(String[] values, char delimiter)
{
return join(Arrays.asList(values), String.valueOf(delimiter));
}
// To match Apache commons-lang: StringUtils.join(values, delimiter)
public static String join(String[] values, String delimiter)
{
return join(Arrays.asList(values), delimiter);
}
public static String join(Collection<?> values)
{
return join(values, ',');
}
public static String join(Collection<?> values, char delimiter)
{
return join(values, String.valueOf(delimiter));
}
public static String join(Collection<?> values, String delimiter)
{
if (values == null)
{
return new String();
}
StringBuffer strbuf = new StringBuffer();
boolean first = true;
for (Object value : values)
{
if (!first) { strbuf.append(delimiter); } else { first = false; }
strbuf.append(value.toString());
}
return strbuf.toString();
}