4

The below code ensures a capacity of 11 internally,

ArrayList list = new ArrayList(11);

so why/when should I use public method ensureCapacity() externally?

list.ensureCapacity(11);

And if there is no use why it is kept public?

public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY;

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}
Milind Vinkar
  • 159
  • 1
  • 9
  • 1
    “*why it is kept public?*” Because “*Once public, forever public*” aka “*compatibility*”. So even if there was no use, there was a requirement to *keep* it public. – Holger Jul 04 '16 at 11:17
  • 7
    Using `ensureCapacity` is a micro-optimization. Unless you are maintaining performance-critical code that processes huge volumes of data, you don't ever need to use it. – Brian Goetz Jul 04 '16 at 15:24

3 Answers3

7

Calling new ArrayList(n) initializes the ArrayList with capacity n.

However, there may be a case where you now want to add a large number of elements to this already created ArrayList and the ArrayList is full. Lets say we want to add x new elements.

It would be more efficient to call list.ensureCapacity(n + x) and then add the elements, than it would be to just add the elements and let the List dynamically resize.

Consider this crude example:

ArrayList<Integer> exampleList = new ArrayList<>(200);

Integer[] exampleArray = new Integer[800];

exampleList.ensureCapacity(1000);

Collections.addAll(exampleList, exampleArray);
explv
  • 2,709
  • 10
  • 17
  • hey I got your point however could you give any example where you will use this ? I am asking this because while creating an application you hardly know what the x in (n+x) will be? And also if you already have large set ,you can just do for example, List data; data = database.getDatabase(); ArrayList books = new ArrayList(); books.addAll(data); – Milind Vinkar Jul 04 '16 at 09:57
  • correct me f I am wrong however in docs for addAll() I found,** public boolean addAll(Collection extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacityInternal(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } ** ,whiich means it internally does same thing ,show why do an explicit call and also all elements are added at once through arrayCopy? – Milind Vinkar Jul 04 '16 at 10:15
  • 1
    @MilindVinkar yes my apologies, I was looking at the incorrect method, there is no use case when using `addAll` as it does essentially the same thing internally. – explv Jul 04 '16 at 10:26
2

You might need to use it when you don't want to resize the arrylist automatically and want to keep control to yourself. e.g. you created an ArrayList of 5 size. If you add 6th element it will create a space for 5+5 i.e 10 elements. If you dont want your arryList to double the size you can use list.ensureCapacity to tell how many elements you need.

This is fine for small data but assume your arrayList grows to 5K.

As per java documentation https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html :

An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
sauumum
  • 1,638
  • 1
  • 19
  • 36
  • So just to clarify, I must insert custom logic to use ensureCapacity() to handle cases where collection already has huge amount of data for example if(size>5000)list.ensureCapacity(n+1000) – Milind Vinkar Jul 04 '16 at 11:38
0

You should use ensureCapacity mainly as any other method that ensure capacity of a growable array: to add a large known in advance number of items without many reallocations, because if you add the list of items one by one there could potentially be many reallocation due to array capacity exhaustion.

Consider a simple scenario where you have a 10 elements array and reallocation happens with 2 as a growth factor, if you add 1024 items you would have 10 reallocations, with ensureCapacity(1034) just one (at start of appending).

Vincenzo Maggio
  • 3,787
  • 26
  • 42
  • While the answer is conceptually correct, the math is slightly off. I thought the growth process was interesting and went through it - the formula is (with Java 11) `new = old + old >> 1`. Assuming an existing 10 element array (and also assuming it is at the default max capacity of 10), the order of growing will be (including the initial 10): `10`, `15`, `22`, `33`, `49`, `73`, `109`, `163`, `244`, `366`, `549`, `823`, `1234`. While the ensureCapacity version copies only 10 elements, the default resizing ends up copying 2,456 elements. – Torque Nov 30 '20 at 14:58