The hierarchy
The classes java.lang.StringBuffer
and java.lang.StringBuilder
have exactly the same interface extend java.lang.AbstractStringBuilder
, which has two main attributes:
char value[];
int count;
There are stored the characters and the actual size of the characters.
About the Buffer
String
is a type that stores a character set. It is immutable, that is, it can not have the modified content as well as its size.
The problem with this is that to create new Strings, for example, by concatenating two or more Strings, a new String as the total size of them must be created in memory. If multiple such operations are performed in sequence, the JVM will need to allocate new memory blocks and run the Garbage Collector to deallocate what is not used at all times. This is very "costly" in terms of performance.
The StringBuffer
appears to solve the problem. A% w / of% is nothing more than a String with a Buffer , that is, a placeholder for new characters that can be modified and makes unnecessary, allocate more memory at all times.
The buffer is simply a vector of characters larger than the actual content. For example, the buffer can have 1000 positions and the actual String only 500. This is controlled by the StringBuffer
attribute. In this example, we could add up to 500 more characters without degrading program performance.
The initial size
In many situations it is important to set the initial size of the buffer to an average size of what you want to use.
By doing count
or new StringBuffer()
, that is, without setting an initial size, we are underutilizing the class. The initial capacity of the buffer is only 16 characters.
This means that if we add more than 16 characters, a new buffer will have to be allocated.
Increasing size
When bursting buffer capacity the next one will be created twice as large. See the calculation of the new buffer capacity in the new StringBuilder()
method of the expandCapacity
class:
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
AbstractStringBuilder
or StringBuffer
?
This is a common question. Look at the Javadoc (links are at the beginning of the answer) and note that both have exactly the same interface, that is, the same methods and method signatures.
What's the difference? Let's look at a basic method in both versions, StringBuilder
.
The version in append(String)
is:
public StringBuilder append(String str) {
super.append(str);
return this;
}
And the version in StringBuilder
is:
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
Did you notice the difference? It's the StringBuffer
!
We say that the class synchronized
is synchronized , while the StringBuffer
class is not synchronized .
Synchronized vs. Not Synced
What are the advantages and disadvantages of being synchronized or not?
When a class is synchronized, it is best suited to work in multithreaded environments, for example, on an application server that serves multiple users at the same time. Imagine multiple threads writing a log in memory, for example.
In this case, only one thread at a time can add content to StringBuilder
. The problem is that this also generates unwanted blocks in execution, because we are not always modifying the class.
If multiple threads just want to read some information from the class, then the synchronization is delaying them for no reason. Just to cite an example, class StringBuffer
has the search method StringBuffer
synchronized.
Already when a class is not synchronized, it is not suitable to be used concurrently by more than one thread, however it obtains the maximum of use to be modified by a single thread and also to be used in the multi-reading mode threads.
As a general rule, if the object will be used only in the scope of a method, not being shared, it is always opted for indexOf
, which was created just for this purpose.
If the object is shared in some way with other classes and it is possible for someone to use it in multiple tiers, StringBuilder
is more appropriate.
This rationale applies to several other classes in the JVM. See, for example, the Hashtable classes, StringBuffer
(not synchronized) and HashMap
(synced only for change but not for reading).
So it's obvious the importance of getting to know the APIs of the language before leaving, always using the same solutions indiscriminately.
For more details, see my another answer here in SO .