This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
StringBuilder vs String concatenation in toString() in Java
Why are StringBuilders better to use than normal String Concatenation?
The java compiler these days is smart enough that it will use StringBuilder to concatenate strings anyway.
This makes the following code identical
System.out.println("test = "+test+" test2 = "+test2);
System.out.println((new StringBuilder()).append("test = ").append(test).append("test2 = ").append(test2).toString());
So if your strings fall on a single executable line, you should never be afraid of using string concatanation.
However if you're looping through an array of something and concatenating the strings together the java runtime will be creating all these new StringBuilder then concatenating them together, so it's more efficient in this case to supply your own single instance of StringBuilder
StringBuilder sb = new StringBuilder();
for(String test : testStrings) {
sb.append(" ").appendtest);
}
Because Strings are immutable. When you do a string concatenation, you create many strings as temporaries that must then be garbage collected. With StringBuilder, there's an underlying mutable data structure, so you just keep using that.
The effect is to both limit the amount of GC and reduce the number of JVM instructions that are executed. Instructions aren't usually a big issue, but I've seen bad uses of string concatenation push a JVM into massive GC loads.
StringBuilder is mutable so you are not creating new string.
StringBuilder does not create new Strings in the pool on operations such as concatenation, substring e.t.c. In short, every time u make an operation on String, a new String is created in the pool.
String x = "abc"
x= x+"def";
so three strings have been created in the pool. "abc", "def". "abcdef".....where as same task would have been achieved by StringBUilder while using only one object.
StringBuilder is recommended over StringBuffer, because StringBuffer is thread safe and have synchronized methods, so until or unless thread safe is required, stringbuilder is recommended as string buffer might cause performance overhead, although negligible.
I decided to put your question to the 'profiler' test by running 3 simple test cases through the YourKit Java Profiler. I performed three tests using String, StringBuilder and StringBuffer.
The source for each is as follows:
public void testString() throws Exception {
for ( int x = 0; x < 10000000; x++ ) {
String s = "the quick brown fox jumped over the lazy dogs. ";
for ( int i = 0 ; i < 5; i++ ) {
s += s;
}
}
}
public void testStringBuilder() throws Exception {
for ( int x = 0; x < 10000000; x++ ) {
StringBuilder s = new StringBuilder("the quick brown fox jumped over the lazy dogs. ");
for ( int i = 0 ; i < 5; i++ ) {
s.append(s);
}
}
}
public void testStringBuffer() throws Exception {
for ( int x = 0; x < 10000000; x++ ) {
StringBuffer s = new StringBuffer("the quick brown fox jumped over the lazy dogs. ");
for ( int i = 0 ; i < 5; i++ ) {
s.append(s);
}
}
}
Each of these test cases was executed with 'Tracing' enabled on a 64-bit JDK1.6_27. Below are the timing results from each test (sorry, had to remove images due to SO limits, posting CSV output instead).
The first thing you'll notice is that in both the String an StringBuffer test, the JVM is using StrinbBuffers as the internal implementation. However, in the String case, the overall performance is much worse. The key to the difference is in the invocation count.
In the String case, use of the concatenation operator ("+=") results in the creation of two StringBuffer instances (see the "Invocation Count" results: 99M vs 48M).
So if you're going to do lots of concatenation, use a StringBuffer directly.
String:
"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testString()","190497","190497","0","1", "7"
"java.lang.StringBuilder.append(String)","117742","0","117742","99825142", "8"
"java.lang.StringBuilder.toString()","46142","0","46142","49912563", "8"
"java.lang.StringBuilder.<init>()","26612","0","26612","49912563", "8"
StringBuilder:
"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuilder()","90179","90179","0","1", "7"
"java.lang.StringBuilder.append(CharSequence)","79212","0","79212","48924577", "8"
"java.lang.StringBuilder.<init>(String)","10966","0","10966","9784916", "8"
StringBuffer:
"Name","Time (ms)","Avg. Time (ms)","Own Time (ms)","Invocation Count","Level"
"com.altosresearch.utils.test.StringsTest.testStringBuffer()","83518","83518","0","1", "7"
"java.lang.StringBuffer.append(StringBuffer)","73207","0","73207","48694049", "8"
"java.lang.StringBuffer.<init>(String)","10311","0","10311","9738810", "8"
Since strings are immutable, you may want to use the StringBuilder class if you're going to alter the String in the code.
String is immutable so every concat creates a new object, Stringbuffer/builder are mutable. A note is offered at this link
Related
We are facing very bad performance hit in our application due to large number of strings : created to log application state.
We are planing to move to String builder at least for the logger.
One confusion I have is :
As string builder is called as such :
StringBuilder sb = new StringBuilder();
sb.append("Very big String object....");
If I am right , "Very big String object...." is a still a constructor creating very large String object(immutable) in memory, which remain in String pool.
So whats the use of String builder than in this case ?, as it will certainly create one more object , that will be though garbage collected.
But the String that is created using String constructor (double qoutes) "Very big String object....", is still in memory pool.
You're not right. "Very big String object...." is a compile-time constant, not a constructor, and the String object representing it will go into the constant pool to be reused every time it's needed. The objects that will be created are the actual builder, its backing character array, and the String produced after you add your log information--all of which will vary with each output statement.
If you were only ever using a fixed output string, then using a StringBuilder wouldn't make sense, but the point of the builder is for the parts that vary.
All that said, if logging is a real performance problem, either the String creation isn't the real bottleneck (and actual I/O for the log messages is), or you're building the log messages even if they're not output (e.g., for DEBUG level log statements). In the latter case, you should simply avoid building them entirely if the logger is disabled; modern log frameworks such as slf4j do this automatically (log.debug() in slf4j simply exits immediately if DEBUG logging is turned off).
StringBuilder improves memory consumption and performance for multiple additions. Lets analyze next example (imagine that javac doesn't optimize any String concatenations):
String s = "a" + "b" + "c" + "d" + ... + "z";
StringBuilder sb = new StringBuilder("a").append("b").append("c")....append("z");
In case of String concatenation with + java will add strings from left to right, creating a new string each time: "ab", then "abc", then "abcd", thus 25 new strings, and each time it will copy the previous result completely. While StringBuilder will simply add each string to its own char[] array, without any redundant objects creation.
Now let n be the number of strings, and l - the length of each string. In this case the complexity of the mth + will be O(l*m), because each time the whole previous strings concatenation is copied. Thus we can make a conclusion that summary time (and memory (!)) complexity will be O(l*n*n) for String case. While in the case of StringBuilder it will be O(l*n).
Also regarding logging - small performance comparison:
#Benchmark
public void stringConcatenation(Blackhole bh) {
// By using all these string we should prevent string builder optimizations.
String a = "start ";
String b = a + "first";
String c = b + " inside ";
String d = c + "second";
String e = d + ", ";
String f = e + 1024;
bh.consume(a);
bh.consume(b);
bh.consume(c);
bh.consume(d);
bh.consume(e);
bh.consume(f);
}
#Benchmark
public void stringBuilder(Blackhole bh) {
StringBuilder sb = new StringBuilder("start ")
.append("first")
.append(" inside ")
.append("second")
.append(", ")
.append(1024);
bh.consume(sb.toString());
}
#Benchmark
public void logback(Blackhole bh) {
// Logback formatting
bh.consume(MessageFormatter.arrayFormat("start {} inside {}, {}", new Object[]{"first", "second", 1024}).getMessage());
}
#Benchmark
public void log4j(Blackhole bh) {
// Log4j formatting
bh.consume(messageFactory.newMessage("start {} inside {}, {}", "first", "second", 1024));
}
And the results:
Benchmark Mode Cnt Score Error Units
LogBenchmark.stringConcatenation thrpt 5 9080147,269 ? 988134,269 ops/s
LogBenchmark.stringBuilder thrpt 5 27136050,849 ? 2776464,863 ops/s
LogBenchmark.logback thrpt 5 3579746,331 ? 346554,072 ops/s
LogBenchmark.log4j thrpt 5 4992342,169 ? 335971,537 ops/s
So as you can see suggested by some guys "use logging framework formatter instead" may not be the better choice if you are actually logging a lot.
StringBuilder class is useful when you want to build a string by concatenating values, and new values are added in different sentences of the code:
StringBuilder sb = new StringBuilder("Counting from 0 to 9: ");
for(int i = 0 ; i < 10 ; i++) {
sb.append(i).append(' ');
}
System.out.println(sb.toString());
This class is used because, in this example, the java string concatenation operator + would provide poor performance.
In your example, you don't need a StringBuilder, since you are constructing a static, inmutable, string object.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Strings are immutable. Stringbuilders are not, so you can append characters at the end. Strings are character arrays if i am not wrong, than why do we use character arrays separately and Strings separately, Do we really need to use character arrays?
Secondly, there are character arrays and then there are Arraylists. Array lists holds complete objects? I am a bit confused actually.
String cat = "c" + "a" + "t";
cat = cat + cat;
StringBuilder sb = new StringBuilder();
sb.append(city);
sb.append(", ");
sb.append(state);
sb.toString();
Char apple[5]={'a','p','p','l','e'};
Arraylist<MyCar>obj = new Arraylist<MyCar>();
Which should be used where?
This Explain the best: between string and stringBuilder
Ref:Correct way to use StringBuilder
Note that the aim (usually) is to reduce memory churn rather than total memory used, to make life a bit easier on the garbage collector.
Will that take memory equal to using String like below?
No, it'll cause more memory churn than just the straight concat you quoted. (Until/unless the JVM optimizer sees that the explicit StringBuilder in the code is unnecessary and optimizes it out, if it can.)
If the author of that code wants to use StringBuilder (there are arguments for, but also against; see note at the end of this answer), better to do it properly (here I'm assuming there aren't actually quotes around id2 and table):
StringBuilder sb = new StringBuilder(some_appropriate_size);
sb.append("select id1, ");
sb.append(id2);
sb.append(" from ");
sb.append(table);
return sb.toString();
Note that I've listed some_appropriate_size in the StringBuilder constructor, so that it starts out with enough capacity for the full content we're going to append. The default size used if you don't specify one is 16 characters, which is usually too small and results in the StringBuilder having to do reallocations to make itself bigger (IIRC, in the Sun/Oracle JDK, it doubles itself [or more, if it knows it needs more to satisfy a specific append] each time it runs out of room).
You may have heard that string concatenation will use a StringBuilder under the covers if compiled with the Sun/Oracle compiler. This is true, it will use one StringBuilder for the overall expression. But it will use the default constructor, which means in the majority of cases, it will have to do a reallocation. It's easier to read, though. Note that this is not true of a series of concatenations. So for instance, this uses one StringBuilder:
return "prefix " + variable1 + " middle " + variable2 + " end";
It roughly translates to:
StringBuilder tmp = new StringBuilder(); // Using default 16 character size
tmp.append("prefix ");
tmp.append(variable1);
tmp.append(" middle ");
tmp.append(variable2);
tmp.append(" end");
return tmp.toString();
So that's okay, although the default constructor and subsequent reallocation(s) isn't ideal, the odds are it's good enough — and the concatenation is a lot more readable.
But that's only for a single expression. Multiple StringBuilders are used for this:
String s;
s = "prefix ";
s += variable1;
s += " middle ";
s += variable2;
s += " end";
return s;
That ends up becoming something like this:
String s;
StringBuilder tmp;
s = "prefix ";
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable1);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" middle ");
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(variable2);
s = tmp.toString();
tmp = new StringBuilder();
tmp.append(s);
tmp.append(" end");
s = tmp.toString();
return s;
...which is pretty ugly.
It's important to remember, though, that in all but a very few cases it doesn't matter and going with readability (which enhances maintainability) is preferred barring a specific performance issue.
Normally String is used for normal string based requirement, and when a String can suffice it.
String Builder is used whenever you want to manipulate and play with the string.
Character Array is used when you want to easily iterate over each and every character
ArrayList is a collection. Use it for holding object of a particular type.
String is immutable object that includes underlying char array.
In your line 2 you discard your String that you created in line 1 and create a new String.
String builder avoids creating new String objects for every separate substring.
Both arrays and Arraylist can contain objects, the main difference is that Arraylist can grow, arrays can not. The second difference is that Arraylist is really a List...
A String uses a char[]. A String is not a char[], in the same way that an ArrayList<String> is not a String[].
ArrayList type is a dynamic data structure. This means that it can grow depending on need. Array is static, meaning it's dimensions do not change over its lifetime.
I have code as follows :
String s = "";
for (My my : myList) {
s += my.getX();
}
Findbugs always reports error when I do this.
I would use + if you are manually concatenating,
String word = "Hello";
word += " World!";
However, if you are iterating and concatenating I would suggest StringBuilder,
StringBuilder sb = new StringBuilder();
for (My my : myList) {
sb.append(my.getX());
}
The String object is immutable in Java. Each + means another object. You could use StringBuffer to minimize the amount of created objects.
Each time you do string+=string, it calls method like this:
private String(String s1, String s2) {
if (s1 == null) {
s1 = "null";
}
if (s2 == null) {
s2 = "null";
}
count = s1.count + s2.count;
value = new char[count];
offset = 0;
System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
}
In case of StringBuilder, it comes to:
final void append0(String string) {
if (string == null) {
appendNull();
return;
}
int adding = string.length();
int newSize = count + adding;
if (newSize > value.length) {
enlargeBuffer(newSize);
}
string.getChars(0, adding, value, count);
count = newSize;
}
As you can clearly conclude, string + string creates a lot of overhead, and in my opinion should be avoided if possible. If you think using StringBuilder is bulky or to long you can just make a method and use it indirectly, like:
public static String scat(String... vargs) {
StringBuilder sb = new StringBuilder();
for (String str : vargs)
sb.append(str);
return sb.toString();
}
And use it like:
String abcd = scat("a","b","c","d");
In C# I'm told its about as same as string.Concat();. In your case it would be wise to write overload for scat, like:
public static String scat(Collection<?> vargs) {
StringBuilder sb = new StringBuilder();
for (Object str : vargs)
sb.append(str);
return sb.toString();
}
Then you can call it with:
result = scat(myList)
The compiler can optimize some thing such as
"foo"+"bar"
To
StringBuilder s1=new StringBuilder();
s1.append("foo").append("bar");
However this is still suboptimal since it starts with a default size of 16. As with many things though you should find your biggest bottle necks and work your way down the list. It doesn't hurt to be in the habbit of using a SB pattern from the get go though, especially if you're able to calculate an optimal initialization size.
Premature optimization can be bad as well as it often reduces readability and is usually completely unnecessary. Use + if it is more readable unless you actually have an overriding concern.
It is not 'always bad' to use "+". Using StringBuffer everywhere can make code really bulky.
If someone put a lot of "+" in the middle of an intensive, time-critical loop, I'd be annoyed. If someone put a lot of "+" in a rarely-used piece of code I would not care.
I would say use plus in the following:
String c = "a" + "b"
And use StringBuilder class everywhere else.
As already mentioned in the first case it will be optimized by the compiler and it's more readable.
One of the reasons why FindBugs should argue about using concatenation operator (be it "+" or "+=") is localizability. In the example you gave it is not so apparent, but in case of the following code it is:
String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses";
If this looks somewhat familiar, you need to change your coding style. The problem is, it will sound great in English, but it could be a nightmare for translators. That's just because you cannot guarantee that order of the sentence will still be the same after translation – some languages will be translated to "1 blah blah", some to "blah blah 3". In such cases you should always use MessageFormat.format() to build compound sentences and using concatenation operator is clearly internationalization bug.
BTW. I put another i18n defect here, could you spot it?
The running time of concatenation of two strings is proportional to the length of the strings. If it is used in a loop running time is always increasing. So if concatenation is needed in a loop its better to use StringBuilder like Anthony suggested.
I read a lot about using StringBuffer and String especially where concatenation is concerned in Java and whether one is thread safe or not.
So, in various Java methods, which should be used?
For example, in a PreparedStatement, should query be a StringBuffer:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
try {
ps = connection.prepareStatement(query);
And then again, in a String utility methods like:
public static String prefixApostrophesWithBackslash(String stringIn) {
String stringOut = stringIn.replaceAll("'", "\\\\'");
return stringOut;
}
And:
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
Should I be using StringBuffers? Especially where repalceAll is not available for such objects anyway.
Thanks
Mr Morgan.
Thanks for all the advice. StringBuffers have been replaced with StringBuilders and Strings replaced with StringBuilders where I've thought it best.
You almost never need to use StringBuffer.
Instead of StringBuffer you probably mean StringBuilder. A StringBuffer is like a StringBuilder except that it also offers thread safety. This thread safety is rarely needed in practice and will just cause your code to run more slowly.
Your question doesn't seem to be about String vs StringBuffer, but about using built-in methods or implementing the code yourself. If there is a built-in method that does exactly what you want, you should probably use it. The chances are it is much better optimized than the code you would write.
There is no simple answer (apart from repeating the mantra of StringBuilder versus StringBuffer ... ). You really have understand a fair bit about what goes on "under the hood" in order to pick the most efficient solution.
In your first example, String is the way to go. The Java compiler can generate pretty much optimal code (using a StringBuilder if necessary) for any expression consisting of a sequence of String concatenations. And, if the strings that are concatenated are all constants or literals, the compiler can actually do the concatenation at compile time.
In your second example, it is not entirely clear whether String or StringBuilder would be better ... or whether they would be roughly equivalent. One would need to look at the code of the java.util.regex.Matcher class to figure this out.
EDIT - I looked at the code, and actually it makes little difference whether you use a String or StringBuilder as the source. Internally the Matcher.replaceAll method creates a new StringBuilder and fills it by appending chunks from the source String and the replacement String.
In your third example, a StringBuilder would clearly be best. A current generation Java compiler is not able to optimize the code (as written) to avoid creating a new String as each character is added.
For the below segment of code
// Removes a char from a String.
public static String removeChar(String stringIn, char c) {
String stringOut = ("");
for (int i = 0; i < stringIn.length(); i++) {
if (stringIn.charAt(i) != c) {
stringOut += stringIn.charAt(i);
}
}
return stringOut;
}
You could just do stringIn.replaceAll(c+"","")
Even in MT code, it's unusual to have multiple threads append stuff to a string. StringBuilder is almost always preferred to StringBuffer.
Modern compilers optimize the code already. So some String additions will be optimized to use StringBuilder and we can keep the String additions if we think, it increases readibility.
Example 1:
String query = ("SELECT * " +
"FROM User " +
"WHERE userName = ?;");
will be optimized to somthing like:
StringBuiler sb = new StringBuilder();
sb.append("SELECT * ");
sb.append("FROM User ");
sb.append("WHERE userName = ?;");
String query = sb.toString();
Example 2:
String numbers = "";
for (int i = 0;i < 20; i++)
numbers = numbers + i;
This can't be optimized and we should use a StringBuilder in code.
I made this observation for SUN jdk1.5+. So for older Java versions or different jdks it can be different. There it could be save to always code StringBuilder (or StringBuffer for jdk 1.4.2 and older).
For cases which can be considered single threaded, the best would be StringBuilder. It does not add any synchronization overhead, while StringBuffer does.
String concatenation by '+' operator is "good" only when you're lazy to use StringBuilder or just want to keep the code easily readable and it is acceptable from performance point of view, like in startup log message "LOG.info("Starting instance " + inst_id + " of " + app_name);"
What is the difference between String and StringBuffer in Java?
Is there a maximum size for String?
String is used to manipulate character strings that cannot be changed (read-only and immutable).
StringBuffer is used to represent characters that can be modified.
Performance wise, StringBuffer is faster when performing concatenations. This is because when you concatenate a String, you are creating a new object (internally) every time since String is immutable.
You can also use StringBuilder which is similar to StringBuffer except it is not synchronized. The maximum size for either of these is Integer.MAX_VALUE (231 - 1 = 2,147,483,647) or maximum heap size divided by 2 (see How many characters can a Java String have?).
More information here.
A String is immutable, i.e. when it's created, it can never change.
A StringBuffer (or its non-synchronized cousin StringBuilder) is used when you need to construct a string piece by piece without the performance overhead of constructing lots of little Strings along the way.
The maximum length for both is Integer.MAX_VALUE, because they are stored internally as arrays, and Java arrays only have an int for their length pseudo-field.
The performance improvement between Strings and StringBuffers for multiple concatenation is quite significant. If you run the following test code, you will see the difference. On my ancient laptop with Java 6, I get these results:
Concat with String took: 1781ms
Concat with StringBuffer took: 0ms
public class Concat
{
public static String concatWithString()
{
String t = "Cat";
for (int i=0; i<10000; i++)
{
t = t + "Dog";
}
return t;
}
public static String concatWithStringBuffer()
{
StringBuffer sb = new StringBuffer("Cat");
for (int i=0; i<10000; i++)
{
sb.append("Dog");
}
return sb.toString();
}
public static void main(String[] args)
{
long start = System.currentTimeMillis();
concatWithString();
System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
start = System.currentTimeMillis();
concatWithStringBuffer();
System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
}
}
String StringBuffer
Immutable Mutable
String s=new String("karthik"); StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy"); sb.append("reddy");
System.out.println(s); System.out.println(sb);
O/P:karthik O/P:karthikreddy
--->once we created a String object ---->once we created a StringBuffer object
we can't perform any changes in the existing we can perform any changes in the existing
object.If we are trying to perform any object.It is nothing but mutablity of
changes with those changes a new object of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object
Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety
String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object
String s="karthik";
--->In this case only one object will be created in scp and s is always pointing to that object only
String is an immutable class. This means that once you instantiate an instance of a string like so:
String str1 = "hello";
The object in memory cannot be altered. Instead you will have to create a new instance, copy the old String and append whatever else as in this example:
String str1 = "hello";
str1 = str1 + " world!";
What is really happening hear is that we are NOT updating the existing str1 object... we are reallocating new memory all together, copying the "hello" data and appending " world!" to the end, then settings the str1 reference to point to this new memory. So it really looks more like this under the hood:
String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;
So it follows that this "copy + paste and move stuff around in memory" process can be very expensive if done repitively especially recursively.
When you are in that situation of having to do things over and over utilize StringBuilder. It is mutable and can append strings to the end of the current one because it's back by an [growing array] (not 100% if that is the actual data structure, could be a list).
From the API:
A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls.
A StringBuffer is used to create a single string from many strings, e.g. when you want to append parts of a String in a loop.
You should use a StringBuilder instead of a StringBuffer when you have only a single Thread accessing the StringBuffer, since the StringBuilder is not synchronized and thus faster.
AFAIK there is no upper limit for String size in Java as a language, but the JVMs probably have an upper limit.
I found interest answer for compare performance String vs StringBuffer by Reggie Hutcherso
Source: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html
Java provides the StringBuffer and String classes, and the String class is used to manipulate character strings that cannot be changed. Simply stated, objects of type String are read only and immutable. The StringBuffer class is used to represent characters that can be modified.
The significant performance difference between these two classes is that StringBuffer is faster than String when performing simple concatenations. In String manipulation code, character strings are routinely concatenated. Using the String class, concatenations are typically performed as follows:
String str = new String ("Stanford ");
str += "Lost!!";
If you were to use StringBuffer to perform the same concatenation, you would need code that looks like this:
StringBuffer str = new StringBuffer ("Stanford ");
str.append("Lost!!");
Developers usually assume that the first example above is more efficient because they think that the second example, which uses the append method for concatenation, is more costly than the first example, which uses the + operator to concatenate two String objects.
The + operator appears innocent, but the code generated produces some surprises. Using a StringBuffer for concatenation can in fact produce code that is significantly faster than using a String. To discover why this is the case, we must examine the generated bytecode from our two examples. The bytecode for the example using String looks like this:
0 new #7 <Class java.lang.String>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method java.lang.String(java.lang.String)>
9 astore_1
10 new #8 <Class java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method java.lang.String valueOf(java.lang.Object)>
18 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
26 invokevirtual #22 <Method java.lang.String toString()>
29 astore_1
The bytecode at locations 0 through 9 is executed for the first line of code, namely:
String str = new String("Stanford ");
Then, the bytecode at location 10 through 29 is executed for the concatenation:
str += "Lost!!";
Things get interesting here. The bytecode generated for the concatenation creates a StringBuffer object, then invokes its append method: the temporary StringBuffer object is created at location 10, and its append method is called at location 23. Because the String class is immutable, a StringBuffer must be used for concatenation.
After the concatenation is performed on the StringBuffer object, it must be converted back into a String. This is done with the call to the toString method at location 26. This method creates a new String object from the temporary StringBuffer object. The creation of this temporary StringBuffer object and its subsequent conversion back into a String object are very expensive.
In summary, the two lines of code above result in the creation of three objects:
A String object at location 0
A StringBuffer object at location 10
A String object at location 26
Now, let's look at the bytecode generated for the example using StringBuffer:
0 new #8 <Class java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method java.lang.StringBuffer(java.lang.String)>
9 astore_1
10 aload_1
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method java.lang.StringBuffer append(java.lang.String)>
16 pop
The bytecode at locations 0 to 9 is executed for the first line of code:
StringBuffer str = new StringBuffer("Stanford ");
The bytecode at location 10 to 16 is then executed for the concatenation:
str.append("Lost!!");
Notice that, as is the case in the first example, this code invokes the append method of a StringBuffer object. Unlike the first example, however, there is no need to create a temporary StringBuffer and then convert it into a String object. This code creates only one object, the StringBuffer, at location 0.
In conclusion, StringBuffer concatenation is significantly faster than String concatenation. Obviously, StringBuffers should be used in this type of operation when possible. If the functionality of the String class is desired, consider using a StringBuffer for concatenation and then performing one conversion to String.
By printing the hashcode of the String/StringBuffer object after any append operation also prove, String object is getting recreated internally every time with new values rather than using the same String object.
public class MutableImmutable {
/**
* #param args
*/
public static void main(String[] args) {
System.out.println("String is immutable");
String s = "test";
System.out.println(s+"::"+s.hashCode());
for (int i = 0; i < 10; i++) {
s += "tre";
System.out.println(s+"::"+s.hashCode());
}
System.out.println("String Buffer is mutable");
StringBuffer strBuf = new StringBuffer("test");
System.out.println(strBuf+"::"+strBuf.hashCode());
for (int i = 0; i < 10; i++) {
strBuf.append("tre");
System.out.println(strBuf+"::"+strBuf.hashCode());
}
}
}
Output:
It prints object value along with its hashcode
String is immutable
test::3556498
testtre::-1422435371
testtretre::-1624680014
testtretretre::-855723339
testtretretretre::2071992018
testtretretretretre::-555654763
testtretretretretretre::-706970638
testtretretretretretretre::1157458037
testtretretretretretretretre::1835043090
testtretretretretretretretretre::1425065813
testtretretretretretretretretretre::-1615970766
String Buffer is mutable
test::28117098
testtre::28117098
testtretre::28117098
testtretretre::28117098
testtretretretre::28117098
testtretretretretre::28117098
testtretretretretretre::28117098
testtretretretretretretre::28117098
testtretretretretretretretre::28117098
testtretretretretretretretretre::28117098
testtretretretretretretretretretre::28117098
A StringBuffer or its younger and faster brother StringBuilder is preferred whenever you're going do to a lot of string concatenations in flavor of
string += newString;
or equivalently
string = string + newString;
because the above constructs implicitly creates new string everytime which will be a huge performance and drop. A StringBuffer / StringBuilder is under the hoods best to be compared with a dynamically expansible List<Character>.
A String is an immutable character array.
A StringBuffer is a mutable character array. Often converted back to String when done mutating.
Since both are an array, the maximum size for both is equal to the maximum size of an integer, which is 2^31-1 (see JavaDoc, also check out the JavaDoc for both String and StringBuffer).This is because the .length argument of an array is a primitive int. (See Arrays).
String is immutable, meaning that when you perform an operation on a String you are really creating a whole new String.
StringBuffer is mutable, and you can append to it as well as reset its length to 0.
In practice, the compiler seems to use StringBuffer during String concatenation for performance reasons.
String is immutable.
Why? Check here.
StringBuffer is not. It is thread safe.
Further questions like when to use which and other concepts can be figured out following this.
Hope this helps.
While I understand that this is not a major differentiating factor, I noticed today that StringBuffer(and StringBuilder) provides some interesting methods that String doesn't.
reverse()
setCharAt()
The differences are
Only in String class + operator is overloaded. We can concat two String object using + operator, but in the case of StringBuffer we can't.
String class is overriding toString(), equals(), hashCode() of Object class, but StringBuffer only overrides toString().
String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1.equals(s2)); // output true
StringBuffer sb1 = new StringBuffer("abc");
StringBuffer sb2 = new StringBuffer("abc");
System.out.println(sb1.equals(sb2)); // output false
String class is both Serializable as well as Comparable, but StringBuffer is only Serializable.
Set<StringBuffer> set = new TreeSet<StringBuffer>();
set.add(sb1);
set.add(sb2);
System.out.println(set); // gives ClassCastException because there is no Comparison mechanism
We can create a String object with and without new operator, but StringBuffer object can only be created using new operator.
String is immutable but StringBuffer is mutable.
StringBuffer is synchronized, whereas String ain't.
StringBuffer is having an in-built reverse() method, but String dosen't have it.
Performance wise StringBuffer is much better than String ; because whenever you apply concatenation on String Object then new String object are created on each concatenation.
Principal Rule : String are immutable(Non Modifiable) and StringBuffer are mutable(Modifiable)
Here is the programmatic experiment where you get the performance difference
public class Test {
public static int LOOP_ITERATION= 100000;
public static void stringTest(){
long startTime = System.currentTimeMillis();
String string = "This";
for(int i=0;i<LOOP_ITERATION;i++){
string = string+"Yasir";
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void stringBufferTest(){
long startTime = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer("This");
for(int i=0;i<LOOP_ITERATION;i++){
stringBuffer.append("Yasir");
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
public static void main(String []args){
stringTest()
stringBufferTest();
}
}
Output of String are in my machine
14800
Output of StringBuffer are in my machine
14