26

Its known that Java ArrayList is implemented using arrays and initializes with capacity of 10 and increases its size by 50% . How to get the current ArrayList capacity not the Size of the ArrayList.

Thx

Guido
  • 46,642
  • 28
  • 120
  • 174
JavaUser
  • 25,542
  • 46
  • 113
  • 139
  • 3
    Why do you need this information? – Bart Kiers Mar 23 '10 at 08:48
  • 3
    Bark ..Nothing specific ..I had this in an interview – JavaUser Mar 23 '10 at 15:02
  • 1
    Google led me here. The reason i need this info -- I have an ArrayBlockingQueue that I'm take()ing through, processing, and storing results in another Collection. Thought it would be nice to use an initial capacity for the results Collection that matches the capacity of the ABQ. Not such an odd use case, no? There are other ways around it for me (e.g. storing capacity as a static final and referencing that), but not necessarily in all cases. – ericsoco Sep 05 '12 at 19:58
  • Look at https://stackoverflow.com/a/3564928/9691976 – Mohammad Kholghi Jul 05 '20 at 17:08

11 Answers11

20

I don't think this is possible. What is your use case? I believe C# ArrayLists have a .capacity property, but the Java ArrayList class doesn't expose this information.

You have the constructor that takes an initial capacity argument, and you have the ensureCapacity() method which you could use to reduce the amount of incremental reallocation.

You also have the trimToSize() method you can use if you are really worried about memory usage.

Ajinkya
  • 22,324
  • 33
  • 110
  • 161
Mark B
  • 183,023
  • 24
  • 297
  • 295
  • 1
    What abt the same case regarding with Vectors ? – JavaUser Mar 23 '10 at 02:07
  • 4
    Vector has a capacity() method that returns the current capacity. Have you taken the time to look at the API at all? http://java.sun.com/j2se/1.4.2/docs/api/java/util/Vector.html – Mark B Mar 23 '10 at 02:11
  • 2
    No mbaird , I am just looking into your answer.Thx – JavaUser Mar 23 '10 at 02:15
  • 2
    How can you decide when to call trimToSize() if you don't know the capacity? It's not efficient to call trimToSize() all the time. It's a mistake not to expose capacity. – jack Mar 19 '17 at 17:45
17

You can get it by reflection:

public abstract class ArrayListHelper {

    static final Field field;
    static {
        try {
            field = ArrayList.class.getDeclaredField("elementData");
            field.setAccessible(true);
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    @SuppressWarnings("unchecked")
    public static <E> int getArrayListCapacity(ArrayList<E> arrayList) {
        try {
            final E[] elementData = (E[]) field.get(arrayList);
            return elementData.length;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
pgras
  • 12,614
  • 4
  • 38
  • 46
  • 7
    This will fail horribly, when the field is not called `elementData`. And since that name is not specified in the API, any implementation (and any version!) is free to call it something else entirely. – Joachim Sauer Mar 23 '10 at 07:42
  • 3
    @JoachimSauer still called elementData, don't see why'd they'd change that, still you can easily modify the code if/when they do! – BaSsGaz Dec 15 '16 at 23:54
  • 2021 still called 'elementData'... this workaround is valid and not bad. – alex Sep 24 '21 at 06:11
  • This workaround [is not valid](https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals) since JDK 17+. Illegal reflective access (making private fields accessible) will fail. Versions after 9 and prior to 16 produce warnings, 16 requires a JVM parameter to make it work and this parameter is removed completely in 17. Don't do this. – predi Dec 06 '22 at 13:33
7

You can get the current capacity of an ArrayList in Java using reflection. Here is an example:

package examples1;

import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Field;

public class Numbers {

    public static void main(String[] args) throws Exception {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        System.out.println(getCapacity(numbers));
    }

    static int getCapacity(List al) throws Exception {
        Field field = ArrayList.class.getDeclaredField("elementData");
        field.setAccessible(true);
        return ((Object[]) field.get(al)).length;
    }
}

This will output: 10

Notes:

  1. getCapacity() method modified from the original at http://javaonlineguide.net/2015/08/find-capacity-of-an-arraylist-in-java-size-vs-capacity-in-java-list-example.html
  2. Note that the default capacity of 10 is granted after the first add to the list. If you try this before adding, you will get an output of 0
  3. To force a capacity without adding, pass it in the constructor like so:

    List<Integer> numbers = new ArrayList<>(20);
    
Shant Dashjian
  • 888
  • 11
  • 20
  • 2
    Oh, many thanks, man. You saved my day! P.S. If you catch exception "No field elementData", I don't know what is it but I switched to NetBeans from Android Studio and exception is gone. – Dyno Cris Apr 09 '19 at 21:05
1

You can use Vector instead of ArrayList. Vector supports capacity() method.

user2632932
  • 97
  • 1
  • 5
  • 6
    The OP clearly wanted the capacity of an `ArrayList`, not a `Vector`. – Manuel Jul 30 '13 at 07:10
  • 1
    Vector can achieve the same as ArrayList. It's Java's fault not to expose capacity. How can you decide when to call trimtosize if you don't know the capacity? It's not efficient to call trimtosize all the time. In such situation change to use Vector is a great idea. – jack Mar 19 '17 at 17:43
1

Looking at ArrayList's spec I see no method that provides this information.

That said, the ensureCapacity method does seem like a step in the right direction (caution: it is does not guarantee a correct answer): When called it ensures that the capacity is at least the specified argument. So, if the ArrayList implementation uses this method to ensure capacity (as opposed to calling some private method/manipulating the relevant fields directly) you can obtain the current capacity by overriding this method. You also need to override trimToSize() in a similar manner.

Of course, this solution is not very portable as a different implementation of ArrayList (on a JVM from another vendor) may do things differently.

Here's how the code should look like

public class CapacityTrackingArrayList<T> extends ArrayList<T> {

   // declare a constructor for each ArrayList constructor ...


   // Now, capacity tracking stuff:
   private int currentCapacity = 10;

   public int getCapacity() { return currentCapacity; }

   public void ensureCapacity(int arg) {
     currentCapacity = arg;
     super.ensureCapacity(arg);
   }

   public void trimToSize() { currentCapacity = size(); super.trimToSize(); }

}
Itay Maman
  • 30,277
  • 10
  • 88
  • 118
  • 1
    ensureCapacity() just ensures that it has at least that much space. If it has more space it will do nothing. If later you keep adding elements so that it needs even more, it will grow. None of these cases would be handled by your example code. All your code will do is allow you to be reminded of what value you passed to ensureCapacity() earlier, which may have no real bearing on what the true capacity is later on. – Mark B Mar 23 '10 at 02:14
  • By all means, I don't say this is a perfect solution nor is it a portable one. It is just a step in the right direction. – Itay Maman Mar 23 '10 at 02:17
1

Default capacity of ArrayList is 10.once the max size is reached,new capacity will be:

new capacity=(currentcapacity*3/2)+1.

Avinash Kumar
  • 288
  • 6
  • 21
1

The whole point of using ArrayList is to dynamically add new element, So there is no specific method to get the capacity of the ArrayList.

Every time we add an element dynamically causes reallocation and since reallocation is costly in terms of time, preventing reallocation improves performance and hence you can manually increase the capacity of ArrayList by calling ensureCapacity() but again you can not find out the capacity of the ArrayList.

K_holla
  • 124
  • 1
  • 3
0

Don't remember if it has but you could do it yourself by looking at the source code of ArrayList. Java developers should take advantage of the source code bundled with the SDK.

instcode
  • 1,495
  • 14
  • 16
  • Not sure how useful this would be to help him find the current capacity at runtime though. Unless he took the source and added a method to expose the capacity, and then used his custom version of ArrayList everywhere. – Mark B Mar 23 '10 at 02:07
  • 1
    Haha, first s.o upvote then s.o else downvote :)) I gave him a rod but you gave him a fish... Now what, he gonna ask for Vector, LinkedList..? :)) – instcode Mar 23 '10 at 02:11
  • @mbaird 'you could do it yourself' probably meant 'you can find out if there is a way to get the capacity by looking at the source code', not 'you can change the source code'. – bjornars Feb 07 '11 at 16:07
0

I just checked out the sun documentation on the ArrayList class, and the only method I saw that related to the capacity was ensureCapacity(int minCapacity), which is not exactly what you want. Good luck!

chama
  • 5,973
  • 14
  • 61
  • 77
0

The default capacity is 2 for an Array List in java. I am not able to find the vague documentation I read a while ago. But the size will be zero upon initialization. Once we add the third element it will creates an array of double the capacity in another memory location. The reference will be shifted accordingly and the previous array will be garbage collected

0

I dont think there is a direct method to check ArrayList Capacity. But, there is a method to Check the Size of the array list.

s.o.p.ln(arraylist.size());

You can say this in interview. We cannot tell the ArrayList Capacity, but we can check the Size. Then, according to the size, we can calculate the Capacity by our own. Initial Capacity of Arraylist = 10. When it is full, new List is formed with a Capacity of CurrentCapacity * (3/2) +1 . So, in this method, you can calculate the capacity of ArrayList.

Hameed
  • 1
  • 1