How does ensureCapacity work in Java?

2019-05-15 00:07发布

问题:

StringBuffer buff1 = new StringBuffer("tuts point");

System.out.println("Old Capacity of buff1 = " + buff1.capacity());
buff1.ensureCapacity(28);
System.out.println("New Capacity of buff1 = " + buff1.capacity());

StringBuffer buff2 = new StringBuffer("compilejksde");

System.out.println("Old Capacity of buff2= " + buff2.capacity());
buff2.ensureCapacity(75);
System.out.println("New Capacity of buff2= " + buff2.capacity());

回答1:

The contract states the following:

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.

So, to explain the output from your program:

Old Capacity of buff1 = 26
New Capacity of buff1 = 54  // Old capacity*2+2 (since it's larger than the argument: 28)
Old Capacity of buff2= 28
New Capacity of buff2= 75   // the argument you gave, 75 (since it's larger than 2*28+2 = 58)


回答2:

You should probably not be using StringBuffer, but StringBuilder instead.... they both accomplish the same basic functionality, but StringBuffer is a thread-safe, synchronized class. That extra functionality makes it slower to use for general single-threaded programming.

Unless you have a good reason, use StringBuilder instead of StringBuffer.

As for the capacity, StringBuffer (and StringBuilder) both have a char[] array internally that is used to store the characters you append. This array can grow, as needed, to contain additional characters.

When you append the letter "a" to an empty StringBuffer, the length will be 1 (just one character), but the capacity will be the length of the char[] array that backs the data, and that will be at least 1 (probably 16, in fact). Thus the toString() is a, the length() is '1', and the capacity will be about 16.

As you append data, the capacity will be increased to contain the larger strings. Expanding the capacity is relatively slow, especially for large StringBuffers because they require larger memory allocations, and collections.

If you know the size of how large your data is going to be before hand, you can extend the capacity to store the final String without having to go though multiple expansions. This saves time.

So, if you know a String will be 1000 characters long, then you should ensureCapacity(1000) early, and save time later.



回答3:

The java.lang.StringBuffer.ensureCapacity() method 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 :

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

See this whole documentation with example.

public void ensureCapacity(int minimumCapacity)

where minimumCapacity is the minimum desired capacity.



回答4:

What is happening?

// initial capacity (of the array behind the scenes) will be 16. 
StringBuffer buff1 = new StringBuffer("tuts point");
//  The above constructor increases the capacity by 16 + stringArgument.length = 16 + 10 = 26 ( hence the output)
System.out.println("Old Capacity of buff1 = " + buff1.capacity()); // 26 ->check

buff1.ensureCapacity(28); // here 28 is minimumcapacity.
// the above line of code calls expandCapacity() of AbstractStringBuilder which does this:
//`(value.length + 1) * 2` i.e, 26+1 * 2 = 54 . Hence the output. 

System.out.println("New Capacity of buff1 = " + buff1.capacity()); //54 --> check

PS : The same applies to the second case.