I was going through the PMD rule AppendCharacterWithChar. It says Avoid concatenating characters as strings in StringBuffer.append. 
StringBuffer sb = new StringBuffer();
  // Avoid this
  sb.append("a");
  // use instead something like this
  StringBuffer sb = new StringBuffer();
  sb.append('a');
Do I really need this PMD rule? Is there much performance difference between the following two piece of code?
String text = new StringBuffer().append("some string").append('c').toString();
String text = new StringBuffer().append("some string").append("c").toString();
                Appending a character as a char will always be faster than appending it as a String.
But does the performance difference matter? If you just do it once, it doesn't. If it is inside a cycle repeating its body a million times, then yes, it might matter.
If you already have the character at compile time, just append it as a character. If it is stored in a variable with String type, don't bother accessing it e.g. with String.charAt(0) or some other ways, simply just append the String.
On a Side Note:
Favor the StringBuilder class to StringBuffer. StringBuilder is faster because its methods are not synchronized (which you don't need in most cases).
On a Side Note #2:
This won't compile:
String text = new StringBuffer().append("some string").append('c');
append() returns StringBuffer for chaining. You need to call toString() on it:
String text = new StringBuffer().append("some string").append('c').toString();
                        Out of curiosity I ran a micro benchmark with jmh (including GC monitoring). Using a String is marginally slower but the difference is minimal: around 5 ns (nanoseconds) per invocation and no significant difference on GC activity.
If you called append("c") instead of append('c') one million times, it would add 5 ms to your program.
Benchmark results, including gc time - n represents the initial length of the StringBuilder:
Benchmark                             (n)  Mode  Cnt     Score     Error   Units
SO28344.appendChar                      0  avgt   30    16.476 ±   0.331   ns/op
SO28343294.appendChar:·gc.time          0  avgt   30   256.000                ms
SO28343294.appendString                 0  avgt   30    22.048 ±   0.345   ns/op
SO28343294.appendString:·gc.time        0  avgt   30   220.000                ms
SO28343294.appendChar                  50  avgt   30    17.323 ±   0.967   ns/op
SO28343294.appendChar:·gc.time         50  avgt   30    67.000                ms
SO28343294.appendString                50  avgt   30    20.944 ±   1.466   ns/op
SO28343294.appendString:·gc.time       50  avgt   30    74.000                ms
SO28343294.appendChar                1000  avgt   30    58.396 ±   0.811   ns/op
SO28343294.appendChar:·gc.time       1000  avgt   30    25.000                ms
SO28343294.appendString              1000  avgt   30    64.572 ±   4.779   ns/op
SO28343294.appendString:·gc.time     1000  avgt   30    24.000                ms
Code:
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
public class SO28343294 {
  @Param({"0", "50", "1000"}) int n;
  Random r = new Random();
  StringBuilder sb;
  String s;
  char c;
  @Setup(Level.Invocation) public void populate() {
    sb = new StringBuilder(n + 5);
    for (int i = 0; i < n; i++) {
      sb.append((char) (r.nextInt(26) + 'a'));
    }
    c = (char) (r.nextInt(26) + 'a');
    s = new String(new char[] { c });
  }
  @Benchmark public StringBuilder appendString() {
    return sb.append(s);
  }
  @Benchmark public StringBuilder appendChar() {
    return sb.append(c);
  }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With