Search code examples
javaappendsonarqubestringbuilderstringbuffer

Sonar complains : use StringBuilder instead of StringBuffer


I'm currently doing a piece of code which must be able to match some regexp and do some replacement inside the string which match the regexp.

In order to do that I'm using the matcher object in java. But as you can see all over internet, all examples use StringBuffer in order to do some replacement using appendreplacement and appendtail method (oracleDoc) .

But when I push my code, Sonar complains about using stringbuffer instead of stringbuilder.

  • Is this warning from Sonar is an error in this case?
  • Is there any library which do the same using stringbuilder?

Apparently some developpers complains about that here.

I find a way to do not use StringBuffer and use StringBuilder but i'm quite sure this is not as efficient as using StringBuffer (and might be a bad practice). You can copy paste inside a junit test this example code below :

    String entry = "Actual 4.11-6 and 13-5";
    String expectedReturn = "Actual 4*11^(-6) and 13^(-5)";

    String number = "(^|\\s)-?\\d+((\\.||,)\\d+){0,1}(.\\d+){0,1}-\\d+";
    Pattern pattern = Pattern.compile(number);
    Matcher matcher = pattern.matcher(entry);

    //USING STRING BUFFER
    StringBuffer stringBuffer = new StringBuffer();
    String substring;
    while(matcher.find()){
        substring = matcher.group(0);
        matcher.appendReplacement(stringBuffer,substring.replace(".","*").replace("-","^(-")+")");
    }
    matcher.appendTail(stringBuffer);

    //USING STRING BUILDER
    matcher = pattern.matcher(entry);
    int lastIndex = 0;
    StringBuilder stringBuilder = new StringBuilder();
    while(matcher.find()){
        stringBuilder.append(entry.substring(lastIndex,matcher.start()));
        substring = matcher.group(0);
        stringBuilder.append(substring.replace(".","*").replace("-","^(-")+")");
        lastIndex = matcher.end();
    }
    stringBuilder.append(entry.substring(lastIndex,entry.length()));

    Assert.assertEquals(expectedReturn,stringBuffer.toString());
    Assert.assertEquals(expectedReturn,stringBuilder.toString());

Info : The matcher which manage stringbuilder for append will be in jdk 9 source code and code review


Solution

  • It's a warning, not an error. Sonar does its job of warning you that StringBuilder is preferable because it is faster. If the API forces you to use StringBuffer then I would use it and silence the warnings.

    I think the real underlying problem with Pattern and both buffers is that StringBuffer and StringBuilder do not share a specific interface for building strings (Appendable is a more generic interface, I think they should share a more specific interface for constructing strings, something like StringConstructor), which would allow you to switch implementation with zero effort (usually).