Java StringBuilder(StringBuffer)'s ensureCapacity(): Why is it doubled and incremented by 2?

difference between string and stringbuffer and stringbuilder in java in tabular form
difference between string and stringbuffer in java in tabular form
difference between string and stringbuilder in java in tabular form
string and stringbuffer in java example
stringbuilder java 8
3 difference between string buffer and string builder
string in java
why string is immutable in java

I have searched about this, but I couldn't find why StringBuilder's ensureCapacity() method won't lengthen the old capacity by just doubling but also adding two.

So, when default capacity of 16 is full, next lengthened value will be 34 unless whole string length doesn't exceed 34. Why shouldn't it be 32?

My best guess is considering for a null character, '\u0000', but I'm not sure. Can anyone tell me why?


I believe it has to do with a simple, if somewhat dumb, way to ensure the corner case of very small strings.

For example, if I have the string

""

and I double it only, I will not have a sufficient size to store anything else in it. If I double it and add a small constant number of spaces, I can assure that my new value is larger than my old one.

Why increment it by two then? Probably a small performance improvement. By adding two instead of 1, I can avoid an intermediate expansion for small expansions (0 to 10 chars detailed below)

"" => expand => "1" => expand => "123" expand => "1234567" expand => "123456789012345"

which is 4 expands compared to

"" => expand => "12" => expand => "123456" => expand => "123456789012"

which is 3 expands. This also works nicely for one char strings (expanding to 10 chars)

"1" => expand => "1234" => expand => "1234567890"

while the 1 char expansion routine looks like

"1" => expand => "123" => expand => "1234567" => expand => "123456789012345"

Finally, an added increment of two tends to word align about 50% of the time, while added increments of one or three would do so about 25% of the time. While this might not seem like a big deal, some architectures cannot accommodate non-aligned reads without expensive interrupt calls to rewrite the read in the CPU, leading to all sorts of performance issues.

String vs StringBuilder vs StringBuffer in Java, Java provides three classes to represent a sequence of characters: String, StringBuffer, and StringBuilder. The String class is an immutable class whereas  Difference between StringBuffer and StringBuilder. Java provides three classes to represent a sequence of characters: String, StringBuffer, and StringBuilder. The String class is an immutable class whereas StringBuffer and StringBuilder classes are mutable. There are many differences between StringBuffer and StringBuilder. The StringBuilder class is introduced since JDK 1.5.


Difference between StringBuffer and StringBuilder, We have called the append() method on sb instance and modified its content. StringBuffer and StringBuilder are mutable objects. 3. Differences. Objects of String are immutable, and objects of StringBuffer and StringBuilder are mutable. StringBuffer and StringBuilder are similar, but StringBuilder is faster and preferred over StringBuffer for single threaded program. If thread safety is needed, then StringBuffer is used. Related Article : Reverse a string in Java (5 Different Ways)


I suppose that object alignment is a key, because length * 2 + 2-strategy is memory-effective (see explanation below).

Let's consider HotSpot JVM.

First of all, java objects are 8-bytes aligned and char array is not an exception.

Secondly, sizeof(object header) equals 8 bytes on 32-bit JVM and 16 bytes on 64-bit JVM with -XX:-UseCompressedOops.

Thus, object body should be aligned by 8 bytes: objectBodySize(charArray) == sizeOf(arrayLength) + sizeOf(arrayValues) == (4 bytes) + (arrayLength * 2 bytes).

If old array length is even, then new array length will always give zero-size alignment.

Examples:

  1. oldCharArrayLength == 6 then newCharArrayLength == 14 and objectBodySize(newCharArray) == 4 + 14 * 2 == 32

  2. oldCharArrayLength == 4 then newCharArrayLength == 10 and objectBodySize(newCharArray) == 4 + 10 * 2 == 24

It's important to note that -XX:+UseCompressedOops flag is available since 1.6 whereas StringBuilder and AbstractStringBuilder are available since 1.5. It means that the strategy above with two additional chars has zero-cost of memory on 64-bit JVM before 1.6, whereas sizeof(object header) == 12 bytes when run on 64-bit JVM with -XX:+UseCompressedOops.

String vs StringBuffer vs StringBuilder, So, now the big question is how do you manipulate String in Java without creating String garbage? StringBuilder and StringBuffer are the answer to this question. StringBuilder is same as the StringBuffer , that is it stores the object in heap and it can also be modified . The main difference between the StringBuffer and StringBuilder is that StringBuilder is also not thread safe. StringBuilder is fast as it is not thread safe .


StringBuilder and StringBuffer in Java, StringBuffer is mutable means one can change the value of the object . The object created through StringBuffer is stored in the heap. StringBuffer has the same methods as the StringBuilder , but each method in StringBuffer is synchronized that is StringBuffer is thread safe . StringBuilder objects are like String objects, except that they can be modified. Hence Java StringBuilder class is also used to create mutable (modifiable) string object. StringBuilder is same as StringBuffer except for one important difference. StringBuilder is not synchronized, which means it is not thread safe.


 public void ensureCapacity(int minimumCapacity) {
     if (minimumCapacity > value.length) {
         expandCapacity(minimumCapacity);
     }
 }



 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);
}

NOTE: value.length is the capacity of the StringBuffer, not the length.

It has nothing to do with a null string because minimum capacity is 16.

What I think is, the memory allocations cost so much time, and if we are calling ensureCapacity() frequently with increasing minimumCapacity , (capacity +1)*2 will allocate a bit more memory and may reduce further allocations and save some time.

lets consider initial capacity as 16,

only with doubling 16 , 32 , 64 , 128 , 256 , 512 , 1024 , 2048 , so on...

with double +2 16 , 34 , 70 , 142 , 286 , 574 , 1150 , 2302 , so on...

Thus the memory will gradually keeping increasing every time and may decrease the no of allocations of memory.

String vs StringBuffer vs StringBuilder in Java, Well, when we compare the above terms, on the factor Mutability. Then, as mentioned before, Strings are immutable while StringBuffer and  StringBuffer(String str): It reserves area for sixteen a lot of characters while not reallocation and accepts a String argument that sets the initial contents of the StringBuffer object. StringBuffer s=new StringBuffer("HELLO"); Do you know String vs StringBuffer vs StringBuilder in Java? StringBuffer Methods. Following are the Java


[PDF] Difference Between String , StringBuilder And StringBuffer Classes , may have characters and substrings inserted in the middle or appended to the end. Appends the specified StringBuffer to this sequence. The characters of the StringBuffer argument are appended, in order, to the contents of this StringBuffer, increasing the length of this StringBuffer by the length of the argument. If sb is null, then the four characters "null" are appended to this StringBuffer.


String vs StringBuilder vs StringBuffer in Java, while StringBuilder is not which makes StringBuilder faster than StringBuffer. 3) Concatenation operator "+" is internally implemented using either StringBuffer or StringBuilder. Java StringBuffer class is used to create mutable (modifiable) string. The StringBuffer class in java is same as String class except it is mutable i.e. it can be changed. A string that can be modified or changed is known as mutable string. StringBuffer and StringBuilder classes are used for creating mutable string.


StringBuffer class in Java, The StringBuilder class was introduced as of Java 5 and the main difference between the StringBuffer and StringBuilder is that StringBuilders methods are not​