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 spl开发者_如何学运维it 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);
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 String
s 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).
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.)
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
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.
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 String
s 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
.
精彩评论