As for join, I believe this might look a little less complicated:
public String join (Collection<String> c) {
StringBuilder sb=new StringBuilder();
for(String s: c)
sb.append(s);
return sb.toString();
}
I don't get to use Java 5 syntax as much as I'd like (Believe it or not, I've been using 1.0.x lately) so I may be a bit rusty, but I'm sure the concept is correct.
edit addition: String appends can be slowish, but if you are working on GUI code or some short-running routine, it really doesn't matter if you take .005 seconds or .006, so if you had a collection called "joinMe" that you want to append to an existing string "target" it wouldn't be horrific to just inline this:
for(String s : joinMe)
target += s;
It's quite inefficient (and a bad habit), but not anything you will be able to perceive unless there are either thousands of strings or this is inside a huge loop or your code is really performance critical.
More importantly, it's easy to remember, short, quick and very readable. Performance isn't always the automatic winner in design choices.
If you wish to join (concatenate) several strings into one, you should use a StringBuilder. It is far better than using
for(String s : joinMe)
target += s;
There is also a slight performance win over StringBuffer, since StringBuilder does not use synchronization.
For a general purpose utility method like this, it will (eventually) be called many times in many situations, so you should make it efficient and not allocate many transient objects. We've profiled many, many different Java apps and almost always find that string concatenation and string/char[] allocations take up a significant amount of time/memory.
Our reusable collection -> string method first calculates the size of the required result and then creates a StringBuilder with that initial size; this avoids unecessary doubling/copying of the internal char[] used when appending strings.
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().toString());
while (iter.hasNext()) {
sb.append(delim);
sb.append(iter.next().toString());
}
return sb.toString();
}
but Collection isn't supported by JSP, so for tag function 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();
}
I didn't want to import an entire Apache library to add a simple join function, so here's my hack.
public String join(String delim, List<String> destinations) {
StringBuilder sb = new StringBuilder();
int delimLength = delim.length();
for (String s: destinations) {
sb.append(s);
sb.append(delim);
}
// we have appended the delimiter to the end
// in the previous for-loop. Let's now remove it.
if (sb.length() >= delimLength) {
return sb.substring(0, sb.length() - delimLength);
} else {
return sb.toString();
}
}
Here is a pretty simple answer. Use += since it is less code and let the optimizer convert it to a StringBuilder for you. Using this method, you don't have to do any "is last" checks in your loop (performance improvement) and you don't have to worry about stripping off any delimiters at the end.
Iterator<String> iter = args.iterator();
output += iter.hasNext() ? iter.next() : "";
while (iter.hasNext()) {
output += "," + iter.next();
}
I see a lot of overly complex implementations of String.Join here. If you don't have Java 1.8, and you don't want to import a new library the below implementation should suffice.
public String join(Collection<String> col, String delim) {
StringBuilder sb = new StringBuilder();
for ( String s : col ) {
if ( sb.length() != 0 ) sb.append(delim);
sb.append(s);
}
return sb.toString();
}