views:

82

answers:

3

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?

+3  A: 

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.

Uri
Thanks for your answer! I didn't put it into a separate function to highlight the fact that I am trying to reuse the 'builder'-variable. Maybe that doesn't matter?
Lars Andren
It doesn't matter. Repurposing variables can actually get you into trouble down the line. Instead, just have variables go out of scope when they're no longer needed.
Gunslinger47
@Gunslinger, I see, thanks! @Uri, thanks for the initial capacity tips.
Lars Andren
@Lars, there are cases where reuse makes sense but in others it is better to dump and start from scratch. I'm not sure what's better here. You could write a utility class that has an instance variable builder that is shared. One advantage for one-builder-per-run is that you could convert a large number of sets in parallel with multiple threads.
Uri
+3  A: 

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

seanizer
@seanizer, nice answer from a fellow taekwondoista. Thank you!
Lars Andren
brief, but inflexible. I get "" substituted for null whether I want it or not, and don't have a skip nulls option... this is why we made Joiner for Guava (see other answer).
Kevin Bourrillion
I usually don't have nulls in my collections, so the brief approach is fine for me, but Guava rocks! Thanks for making that happen...
seanizer
Since you don't expect nulls, you'd like your joiner to blow up if you *did* have a null -- which is what Guava's Joiner does by default. :-)
Kevin Bourrillion
ok, I'm sold. when is the first release version due?
seanizer
+3  A: 

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.

Cowan
@Cowan: What is the difference betweend guava-libraries and google collection library?
Shervin
the main difference is that guava knows about generics and commons/collections doesn't, but apart from that: they are two different libraries written by two different teams that solve some similar problems (and some non-similar ones) using different approaches
seanizer
@seanizer, Shervin was asking about guava vs google-collections, not guava vs commons :) Shervin - guava is simply the replacement for google-collections. As the project increased in scope, it stopped being limited to collections-only things so a name change was in order. google-collections should basically be considered deprecated, guava is a drop-in replacement with bug fixes + more features.
Cowan
oops, sorry. misread that
seanizer