Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logic used in ensureCapacity method in ArrayList

Tags:

java

I was going through the source code of ArrayList. I came across the method ensureCapacity() which increases the capacity of the data array used internally. In that, the new capacity of the data array was increased based on logic int newCapacity = (oldCapacity * 3)/2 + 1; where old capacity is the current data array size. Is there any particular reason for choosing (oldCapacity * 3)/2 + 1 this as new array size, if so what is it?

/**
 * Increases the capacity of this <tt>ArrayList</tt> instance, if
 * necessary, to ensure that it can hold at least the number of elements
 * specified by the minimum capacity argument.
 *
 * @param   minCapacity   the desired minimum capacity
 */
public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
    Object oldData[] = elementData;
    int newCapacity = (oldCapacity * 3)/2 + 1;
        if (newCapacity < minCapacity)
    newCapacity = minCapacity;
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
}
}

Thanks in advance ...

like image 866
vcosk Avatar asked Jul 26 '10 15:07

vcosk


2 Answers

The only guarantee made in the JavaDoc is that adding a new element has constant amortized time. That means that the average time of adding a new element to the array is constant. Sometimes it might take a bit longer (like when trying to resize the array), but overall these cases are rare enough for it not to affect the average too much.

So for them to be able to respect that guarantee they need to make sure the resizing happens rarely enough as to not affect the average adding time. They use a percent of the current capacity for the new capacity for this reason. If the resize would be something like oldCapacity + 50 the array would be too big for small arrayLists, but if you want to add a few thousand elements, resizing every 50 elements would bring the performance way down. This way the capacity increases exponentially (if you already added a lot of elements, chances are you will add more, so they increase the capacity by more) so it doesn't degrade the performance too much.

As to why they chose 50%, perhaps they felt that doubling (or more) the capacity might be overkill (would consume too much extra memory for very large ArrayLists), and going too low (like perhaps 10-25%) would degrade the performance too much (by doing too many reallocations), so probably +50% offered good enough performance, without taking too much extra memory. I'm guessing they did some performance tests before deciding on the value.

like image 141
Andrei Fierbinteanu Avatar answered Sep 20 '22 10:09

Andrei Fierbinteanu


It grows the list by 50% every time it is called, to prevent allocating the world too soon. The + 1 is meant to catch situations where the list was inititalised with a size of 1 :)

like image 41
rsp Avatar answered Sep 22 '22 10:09

rsp