0

I created a StringBuilder object without any value and appended some values afterwards. I later wanted to replace the object with an entirely different string.

Here's the code:

StringBuilder finalVersion = new StringBuilder(); finalVersion.append("6.0") for (int i = 0; i < list.length(); i++) { if(/*...*/){ finalVersion.append(".2"); } else { finalVersion.append(".1"); } if (/*...*/) { if (/*...*/) { finalVersion = new StringBuilder("Invalid parameter")); } } } 

What I've done is I created a new object to change the value, but perhaps there is a better approach without using stringBuilder.setLength(0);.

Could someone help?

4
  • 2
    There's nothing wrong with creating a new instance. Commented Aug 15, 2018 at 0:27
  • yeah, I agree, but it sounds strange for some quality tools, I mean, is really necessery create another object to set it? Commented Aug 15, 2018 at 0:32
  • If creating a new instance is unacceptable to you, setlength is your only other option. Commented Aug 15, 2018 at 0:38
  • take a look at the answer. Commented Aug 15, 2018 at 1:09

2 Answers 2

4

To solve it I created a new object to change the value but I guess there is a better approach without use sb.setLength(0)

Both of those are good approaches. Another is sb.delete(0, sb.length()).

And when you want to replace the existing string content, sb.replace(0, sb.length(), "new content") is another option.

It really depends what your goal is:

  • Calling new StringBuffer(...) will give you a freshly allocated object with either the default capacity or a capacity that you specify.

  • The setLength, delete and replace approaches will recycle the existing object. This has advantages and disadvantages.

    • On the plus side, you don't allocate a new object1 ... so less garbage.

    • On the minus side, the string buffer uses the same amount of space as before, whether or not it needs to. Also, if you do this repeatedly, the chances are that the buffer and its backing array will be tenured by the GC, adding to the long-term memory load. You can free the unused capacity by calling sb.trimToSize(), but that is liable to cause a reallocation; i.e. what you were trying to avoid by not using new.

My advice would be to use new unless either the context means that you can't, or your profiling tells you that new is generating too much garbage.

Looking at the code2, I think that setLength should be marginally faster than delete for emptying a StringBuffer. It gets more complicated when you are replacing the contents with new contents. Now you are comparing

 sb.setLength(); sb.append("new content"); 

versus

 sb.replace(0, sb.length(), "new content"); 

It needs to be measured ... if you care enough3 about performance to be comparing the cases.


1 - Unless the replacement string is large enough that the buffer needs to grow to hold it.

2 - By my reading of various versions of the StringBuilder and AbstractStringBuilder code, the delete method will always call System.arraycopy. However, to understand the performance impact, one would need to benchmark this carefully for different sizes of StringBuilder and across different Java versions.

3 - Actually, if you need to care. Beware the evils of premature optimization.

Sign up to request clarification or add additional context in comments.

1 Comment

What a nice description! It will help me in the future. Thank you very much.
2

You can use replace. This method doesn't create a new StringBuilder object.

builder.replace(0, b.length(), "Invalid parameter"); 

Or, if doing it in two statements is fine with you, you can setLength(0), then append.

But really, you shouldn't worry about creating a new StringBuilder unless you actually encounter performance problems.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.