When should we change a String to a Stringbuilder?

好久不见. 提交于 2019-12-22 10:48:35

问题


In an application a String is a often used data type. What we know, is that the mutation of a String uses lots of memory. So what we can do is to use a StringBuilder/StringBuffer.

But at what point should we change to StringBuilder?
And what should we do, when we have to split it or to remplace characters in there?

eg:

 //original:
 String[] split = string.split("?");  
 //better? :  
 String[] split = stringBuilder.toString().split("?);

or

 //original:
 String replacedString = string.replace("l","st");  
 //better? :  
 String replacedString = stringBuilder.toString().replace("l","st");  
 //or  
 StringBuilder replacedStringBuilder = new StringBuilder(stringBuilder.toString().replace("l","st);

回答1:


What we know, is that the mutation of a String uses lots of memory.

That is incorrect. Strings cannot be mutated. They are immutable.

What you are actually talking about is building a String from other strings. That can use a lot more memory than is necessary, but it depends how you build the string.

So what we can do is to use a StringBuilder/StringBuffer.

Using a StringBuilder will help in some circumstances:

  String res = "";
  for (String s : ...) {
      res = res + s;
  }

(If the loop iterates many times then optimizing the above to use a StringBuilder could be worthwhile.)

But in other circumstances it is a waste of time:

  String res = s1 + s2 + s3 + s4 + s5;

(It is a waste of time to optimize the above to use a StringBuilder because the Java compiler will automatically translate the expression into code that creates and uses a StringBuilder.)

You should only ever use a StringBuffer instead of a StringBuilder when the string needs to be accessed and/or updated by more than one thread; i.e. when it needs to be thread-safe.

But at what point should we change to StringBuilder?

The simple answer is to only do it when the profiler tells you that you have a performance problem in your string handling / processing.

Generally speaking, StringBuilders are used for building strings rather as the primary representation of the strings.

And what should we do, when we have to split it or to replace characters in there?

Then you have to review your decision to use a StringBuilder / StringBuffer as your primary representation at that point. And if it is still warranted you have to figure out how to do the operation using the API you have chosen. (This may entail converting to a String, performing the operation and then creating a new StringBuilder from the result.)




回答2:


In your examples, there are no benefits in using a StringBuilder, since you use the toString method to create an immutable String out of your StringBuilder.

You should only copy the contents of a StringBuilder into a String after you are done appending it (or modifying it in some other way).

The problem with Java's StringBuilder is that it lacks some methods you get when using a plain string (check this thread, for example: How to implement StringBuilder.replace(String, String)).

What we know, is that a String uses lots of memory.

Actually, to be precise, a String uses less memory than a StringBuilder with equivalent contents. A StringBuilder class has some additional constant overhead, and usually has a preallocated buffer to store more data than needed at any given moment (to reduce allocations). The issue with Strings is that they are immutable, which means Java needs to create a new instance whenever you need to change its contents.

To conclude, StringBuilder is not designed for the operations you mentioned (split and replace), and it won't yield much better performance in any case. A split method cannot benefit from StringBuilder's mutability, since it creates an array of immutable strings as its output anyway. A replace method still needs to iterate through the entire string, and do a lot of copying if replaced string is not the same size as the searched one.

If you need to do a lot of appending, then go for a StringBuilder. Since it uses a "mutable" array of characters under the hood, adding data to the end will be especially efficient.

This article compares the performance of several StringBuilder and String methods (although I would take the Concatenation part with reserve, because it doesn't mention dynamic string appending at all and concentrates on a single Join operation only).




回答3:


If you frequently modify the string, go with StringBuilder. Otherwise, if it's immutable anyway, go with String.

To answer your question on how to replace characters, check this out: http://download.oracle.com/javase/tutorial/java/data/buffers.html. StringBuilder operations is what you want.

Here's another good write-up on StringBuilder: http://www.yoda.arachsys.com/csharp/stringbuilder.html




回答4:


If you need to lot of alter operations on your String, then you can go for StringBuilder. Go for StringBuffer if you are in multithreaded application.




回答5:


Both a String and a StringBuilder use about the same amount of memory. Why do you think it is “much”?

If you have measured (for example with jmap -histo:live) that the classes [C and java.lang.String take up most of the memory in the heap, only then should you think further in this direction.

Maybe there are multiple strings with the same value. Then, since Strings are immutable, you could intern the duplicate strings. Don't use String.intern for it, since it has bad performance characteristics, but Google Guava's Interner.



来源:https://stackoverflow.com/questions/7510422/when-should-we-change-a-string-to-a-stringbuilder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!