ensureCapacity(int minimumCapacity) method in StringBuffer class

As per the oracle docs, refer to this link here

public void ensureCapacity(int minimumCapacity)

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.

I am trying to clear it with a code sample:

    StringBuffer buff1 = new StringBuffer("tuts point");
    System.out.println("buffer1 = " + buff1);        // lenght = 10

    // returns the current capacity of the string buffer 1
    System.out.println("Old Capacity = " + buff1.capacity());  // capacity = 16+10=26 characters
    /*
     * increases the capacity, as needed, to the specified amount in the
     * given string buffer object
     */
    // returns twice the capacity plus 2
    buff1.ensureCapacity(30);
    System.out.println("New Capacity = " + buff1.capacity()); // 26*2 + 2 = 54

If the minimumCapacity argument in the ensureCapacity methods is in between 27 - 53, then i do get the expected answer(returns twice the capacity plus 2). However, if the argument is>=55, the capacity is equal to this argument only.

    // does not return (twice the capacity plus 2)
    buff1.ensureCapacity(55);
    System.out.println("New Capacity = " + buff1.capacity());  // 55

Why 55 is the answer here?

Upvotes: 0

Views: 1364

Answers (2)

PeterK
PeterK

Reputation: 1723

It's due to this call on the AbstractStringBuilder class:

void expandCapacity(int minimumCapacity) {
    int newCapacity = value.length * 2 + 2;
    if (newCapacity - minimumCapacity < 0)
        newCapacity = minimumCapacity;
    if (newCapacity < 0) {
        if (minimumCapacity < 0) // overflow
            throw new OutOfMemoryError();
        newCapacity = Integer.MAX_VALUE;
    }
    value = Arrays.copyOf(value, newCapacity);
}

So, when it increases the capacity, it will increase the capacity by a minimum of (2 * original caparicty) + 2, to the value provided, whichever one is larger.

if the capacity is 26, and you pass 30:

(26 * 2) + 2 = 54, this is more than 30, so the new capacity will be 54.

if the capacity is 26, and you pass 55:

(26 * 2) + 2 = 54, this is less than 55, so the new capacity will be 55.

Upvotes: 2

Doon
Doon

Reputation: 20232

I am sure the answer is going to be implementation detail of the vm, but

for example

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/StringBuffer.java#StringBuffer.ensureCapacity%28int%29

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

which calls expandCapacity in AbstractStringBuilder

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/AbstractStringBuilder.java#AbstractStringBuilder.expandCapacity%28int%29

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

but I don't see it returning 55. So more code exploring. is needed (Also this the openjdk source. not sure what has changed or is different to your vm

Upvotes: 1

Related Questions