将 Set < String > 的内容放到单个 String 中的最快方法是使用空格分隔单词吗?

我有一些 Set<String>,并希望将其中的每一个转换成一个单一的 String,其中原来的 Set的每个元素由一个空格“”分隔。 天真的第一种方法是这样做

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();

有谁能想到一个更快、更漂亮或者更有效率的方法来做这件事吗?

138262 次浏览

I'm confused about the code replication, why not factor it into a function that takes one set and returns one string?

Other than that, I'm not sure that there is much that you can do, except maybe giving the stringbuilder a hint about the expected capacity (if you can calculate it based on set size and reasonable expectation of string length).

There are library functions for this as well, but I doubt they're significantly more efficient.

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.

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.

I use this method:

public static String join(Set<String> set, String sep) {
String result = null;
if(set != null) {
StringBuilder sb = new StringBuilder();
Iterator<String> it = set.iterator();
if(it.hasNext()) {
sb.append(it.next());
}
while(it.hasNext()) {
sb.append(sep).append(it.next());
}
result = sb.toString();
}
return result;
}

I don't have the StringUtil library available (I have no choice over that) so using standard Java I came up with this ..

If you're confident that your set data won't include any commas or square brackets, you could use:

mySet.toString().replaceAll("\\[|\\]","").replaceAll(","," ");

A set of "a", "b", "c" converts via .toString() to string "[a,b,c]".

Then replace the extra punctuation as necesary.

Filth.

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);

This can be done by creating a stream out of the set and then combine the elements using a reduce operation as shown below (for more details about Java 8 streams check here):

Optional<String> joinedString = set1.stream().reduce(new
BinaryOperator<String>() {


@Override
public String apply(String t, String u) {


return t + " " + u;
}
});
return joinedString.orElse("");

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);
}