Fastest way to put contents of Set<String> to a single String with words separated by a whitespace?

I have a few Set<String>s and want to transform each of these into a single String where each element of the original Set is separated by a whitespace " ". A naive first approach is doing it like this

Set<String> set_1;
Set<String> set_2;

StringBuilder builder = new StringBuilder();
for (String str : set_1) {
  builder.append(str).append(" ");
}

this.string_1 = builder.toString();

builder = new StringBuilder();
for (String str : set_2) {
  builder.append(str).append(" ");
}

this.string_2 = builder.toString();

Can anyone think of a faster, prettier or more efficient way to do this?


Solution 1:

With commons/lang you can do this using StringUtils.join:

String str_1 = StringUtils.join(set_1, " ");

You can't really beat that for brevity.

Update:

Re-reading this answer, I would prefer the other answer regarding Guava's Joiner now. In fact, these days I don't go near apache commons.

Another Update:

Java 8 introduced the method String.join()

String joined = String.join(",", set);

While this isn't as flexible as the Guava version, it's handy when you don't have the Guava library on your classpath.

Solution 2:

If you are using Java 8, you can use the native

String.join(CharSequence delimiter, Iterable<? extends CharSequence> elements)

method:

Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter. For example:

 Set<String> strings = new LinkedHashSet<>();
 strings.add("Java"); strings.add("is");
 strings.add("very"); strings.add("cool");
 String message = String.join("-", strings);
 //message returned is: "Java-is-very-cool"

Set implements Iterable, so simply use:

String.join(" ", set_1);

Solution 3:

As a counterpoint to Seanizer's commons-lang answer, if you're using Google's Guava Libraries (which I'd consider the 'successor' to commons-lang, in many ways), you'd use Joiner:

Joiner.on(" ").join(set_1);

with the advantage of a few helper methods to do things like:

Joiner.on(" ").skipNulls().join(set_1);
// If 2nd item was null, would produce "1, 3"

or

Joiner.on(" ").useForNull("<unknown>").join(set_1);
// If 2nd item was null, would produce "1, <unknown>, 3"

It also has support for appending direct to StringBuilders and Writers, and other such niceties.

Solution 4:

Maybe a shorter solution:

public String test78 (Set<String> set) {
    return set
        .stream()
        .collect(Collectors.joining(" "));
}

or

public String test77 (Set<String> set) {
    return set
        .stream()
        .reduce("", (a,b)->(a + " " + b));
}

but native, definitely faster

public String test76 (Set<String> set) {
    return String.join(" ", set);
}