3

What I'm referring to is concatenating Strings with a certain String in the middle, such as concatenating sentences separated by a period, or parameter lists with a comma. I know you can use libraries, but sometimes these can't do what you want, like when you want to generate the phrases you are concatenating. So far I've come up with two solutions,

StringBuffer sentence = new StringBuffer();
String period = "";
for ( int i = 0; i < sentences.length; i++ ) {
    sentence.append( period + sentences[i] );
    period = ". ";
}

which suffers from the redundant reassignment of period. There is also

StringBuffer actualParameters = new StringBuffer();
actualParameters.append( parameters[0] );
for ( int i = 1; i < parameters.length; i++ ) {
    actualParameters.append( ", " + parameters[i] );
}

which removes the reassignment but which still looks unappealing. Any other solutions are greatly appreciated.

Paweł Obrok
  • 22,568
  • 8
  • 74
  • 70
Sean Kelleher
  • 1,952
  • 1
  • 23
  • 34

4 Answers4

3

There is a family of functions in Apache Commons Lang that does just that.

If you have to code it yourself, the way I usually do this sort of thing is as follows:

StringBuilder sb = new StringBuilder();
for (String sentence : sentences) {
    if (sb.length() != 0) {
        sb.append(". ");
    }
    sb.append(sentence);
}

This version permits sentences to be any iterable (returning strings). Also note the use of StringBuilder instead of StringBuffer.

It is easy to generalize this to something akin to org.apache.commons.lang.StringUtils.join.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
1

Seems like a common question!

Remove last character of a StringBuilder?

That would lead to something like:

StringBuffer sentence = new StringBuffer();
String separator = ", ";
for ( int i = 0; i < sentences.length; i++ ) {
    sentence.append( sentences[i] )
    sentence.append( separator );
}
sentence.setLength(sentence.length() - separator.length());
Community
  • 1
  • 1
Duane
  • 281
  • 1
  • 5
  • +1 Very nice solution taking constant time, thinking outside the box :) (`sb` needs to be replaced with `sentence`, though) And thanks for the link. – Sean Kelleher Jul 28 '11 at 10:50
  • don't use `+` if you are already using a StringBuffer! Use a second `append`! The main reason for using the StringBuffer is to avoid `+` which creates an additional StringBuffer (each interaction). – user85421 Jul 28 '11 at 11:29
  • this crashes if `sentences` is empty – Mingwei Samuel Sep 09 '16 at 02:47
1

If you have at least one string then:

String join(String separator, String... strings)
{
    String s = strings[0];
    for (int i = 1; i < strings.length; i++) {
        s += separator + strings[i]; 
    }
    return s;
}
  • This is actually the same as the second solution I have presented except it is using `String` concatenation to build up the result, although this would not be recommended for the reasons outlined in other comments, in particular that made by Carlos Heuberger. – Sean Kelleher Jul 28 '11 at 13:49
  • Modern Java compilers convert String concatenation to StringBuilder + append() calls. Try using javap -c on the class to see the generated code. Although this isn't always as efficient as hand generated code it can be, but always has the benefit of simpler to follow source code. – Mark Howell Jul 29 '11 at 07:02
0
public String join(String sep, String... parts) {
  boolean first = true;
  final StringBuilder sb = new StringBuilder();
  for(String part: parts) {
    if(first)
      first = false;
    else
      sb.append(sep);
    sb.append(part);
  }
}

Don't use StringBuffer because of unnecessary synchronisation and "+" operator, because this will create unnecassry intemediate String objects.

vanje
  • 10,180
  • 2
  • 31
  • 47
  • +1 for the information about StringBuffer and "+" operator, -1 for the code. It again suffers from the added complexity of an extra conditional that the other two answers have... – Sean Kelleher Jul 28 '11 at 10:47