16

I noticed that the capacity method returns StringBuilder capacity without a logic way ... sometime its value is equals to the string length other time it's greater...

is there an equation for know which is its logic?

xdevel2000
  • 19,270
  • 35
  • 120
  • 188
  • Why do you care about the `capacity`? It automatically grows to accomodate whatever is necessary. You can play with it to improve performance, but it's still asymptotically linear. – polygenelubricants Jul 06 '10 at 09:26
  • 6
    There are questions about `capacity` vs. `length` in the OCA exam so to some people the issue does mean a lot. – Igor Soudakevitch May 12 '16 at 08:11

8 Answers8

15

When you append to the StringBuilder, the following logic happens:

if (newCount > value.length) {
    expandCapacity(newCount);
}

where newCount is the number of characters needed, and value.length is the current size of the buffer.

expandCapacity simply increases the size of the backing char[]

The ensureCapacity() method is the public way to call expandCapacity(), and its docs say:

Ensures that the capacity is at least equal to the specified minimum. If the current capacity is less than the argument, then a new internal array is allocated with greater capacity. The new capacity is the larger of:

  • The minimumCapacity argument.
  • Twice the old capacity, plus 2.

If the minimumCapacity argument is nonpositive, this method takes no action and simply returns.

Bozho
  • 554,002
  • 136
  • 1,025
  • 1,121
  • 3
    yes but if I have: StringBuilder str = new StringBuilder(); // capacity 16 str.append("1111111111111111111"); capacity 32 length 19 According to the equation why capacity is not 16 * 2 + 2 = 34?? – xdevel2000 Jul 06 '10 at 07:51
  • Note that this is an implementation detail, the doc does not guarantee that the append methods call `ensureCapacity`. – Marcono1234 Nov 02 '19 at 14:47
14

I will try to explain this with some example.

public class StringBuilderDemo {
     public static void main(String[] args) {
         StringBuilder sb = new StringBuilder();
         System.out.println(sb.length());
         System.out.println(sb.capacity());
     }
}

length() - the length of the character sequence in the builder since this stringbuilder doesn't contain any content, its length will be 0.

capacity() - the number of character spaces that have been allocated. When you try to construct a stringbuilder with empty content, by default it takes the initialize size as length+16 which is 0+16. so capacity would return 16 here.

Note: The capacity, which is returned by the capacity() method, is always greater than or equal to the length (usually greater than) and will automatically expand as necessary to accommodate additions to the string builder.

The logic behind the capacity function:

  1. If you don't initialize stringbuilder with any content, default capacity will be taken as 16 characters capacity.
  2. If you initialize stringbuilder with any content, then capacity will be content length+16.
  3. When you add new content to stringbuilder object, if current capacity is not sufficient to take new value, then it will grow by (previous array capacity+1)*2.

This analysis is take from actual StringBuilder.java code

Priyantha
  • 3,687
  • 4
  • 21
  • 40
user1923551
  • 4,396
  • 32
  • 28
4

This function does something different than you expect - it gives you the max number of chars this StringBuilder instance memory can hold at this time.

String Builder must read

InsertNickHere
  • 3,507
  • 3
  • 24
  • 23
2

Here's the logic: If you define a new instance of the StringBuilder class without a constructor, like so new StringBuilder(); the default capacity is 16. A constructor can be either an int or a String. For a String constructor, the default capacity is calculated like this

int newCapacity = string.length() + 16;

For an int constructor, the capacity is calculated like this

int newCapacity = intSpecified + 16;

If a new String is appended to the StringBuilder and the new length of the String is greater than the current capacity, then the capacity is calculated like this:

int newCapacity = (oldCapacity + 1) * 2;
Ayokunle Paul
  • 213
  • 1
  • 8
1

EDIT: Apologies - the below is information on .NET's StringBuilder, and is not strictly relevant to the original question.

http://johnnycoder.com/blog/2009/01/05/stringbuilder-required-capacity-algorithm/

StringBuilder allocates space for substrings you might add to it (much like List creates space the array it wraps). If you want the actual length of the string, use StringBuilder.Length.

Alex Humphrey
  • 5,545
  • 3
  • 20
  • 39
1

From the API:

Every string builder has a capacity. As long as the length of the character sequence contained in the string builder does not exceed the capacity, it is not necessary to allocate a new internal buffer. If the internal buffer overflows, it is automatically made larger.

Whenever you append something, there is a check to make sure that the updated StringBuilder won't exceed its capacity, and if it does, the internal storage of the StringBuilder is resized:

int len = str.length();
int newCount = count + len;
if (newCount > value.length)
  expandCapacity(newCount);

When data is added to it that exceeds its capacity it is re-sized according to the following formula:

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

See the src.zip file that comes with the JDK for more information. (Above snippets taken from the 1.6 JDK)

Catchwa
  • 5,635
  • 2
  • 31
  • 56
0

You can go inside the JDK code and see how it works, it is based on a char array: new char[capacity], it is similar to how the ArrayList works (When to use LinkedList over ArrayList?). Both use arrays to be 'hardware efficient', the trick is to allocate a large chunk of memory and work in it until you run out of memory and need the next big chunk to continue (expand/grow).

Community
  • 1
  • 1
Christophe Roussy
  • 13,732
  • 2
  • 75
  • 75
0

in Java 1.8

public AbstractStringBuilder append(String str) {
    if (str == null)
        return appendNull();
    int len = str.length();
    ensureCapacityInternal(count + len);
    str.getChars(0, len, value, count);
    count += len;
    return this;
}

private void ensureCapacityInternal(int minimumCapacity) {
    // overflow-conscious code
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                newCapacity(minimumCapacity));
    }
}

for example :

StringBuilder str = new StringBuilder();  
System.out.println(str.capacity()); //16

str.append("123456789012345"); 
System.out.println(str.capacity()); //16

str.append("12345678901234567890"); 
System.out.println(str.capacity()); // 15 + 20 = 35
HenryChuang
  • 1,411
  • 17
  • 27