views:

279

answers:

9

How to find the capacity of the ArrayList?

+12  A: 

No you cannot ! Java ArrayList do not provide a way to access its current capacity.

You can only construct an ArrayList specifying an initial capacity using constructor ArrayList(int initialCapacity) or increase the capacity by calling ensureCapacity().

Gopi
"No you cannot." An excalmation mark would have made this hilarious.
klez
@klez is that now :) ?
Gopi
Now you get my upvote sir!
klez
@klex I would have put one more exclamation mark now if one could vote up twice for an answer on SO :P
Gopi
+1  A: 

You don't need to worry about the capacity, that is an internal implementation detail. If the internal array fills, then it will expand. You can find out how many elements are currently in your ArrayList with the size() method.

Noel M
+1  A: 

From the specification: "The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost."

So there's no way to tell what the current capacity is, nor how it grows.

Jeroen Rosenberg
A: 

Do you need this at runtime or is it ok to get while performing testing? If its testing you can usually see the capacity using your favourite IDE debugger. I don't have the exact number, but 1.7 is usually the capacity growth size. So if you create an arraylist with 10 items, java will make it size 17.

steve
A: 

The API doesn't provide it. Internally, the capacity is multiplied by a factor whenever add(..) is called while in full capacity. However, the Java specification doesn't say anything about this constant factor... Sun's implementation uses a factor of 1.5, so you have an upper bound of 1.5*size() for the capacity.

Remember that you can use trimToSize() to "compact" the list and make the capacity equal to size().

Eyal Schneider
+4  A: 

The ArrayList is an abstraction for an automatically growable List of elements. You rarely need to know its capacity. Consider Effective Java 2nd Edition, Item 52: Refer to objects by their interfaces. As much as practical, you should not even care if it's an ArrayList or a LinkedList; it's just a List.

That said, these methods may be of interest to you:

  • ArrayList(int initialCapacity)
    • Constructs an empty list with the specified initial capacity.
  • void ensureCapacity(int minCapacity)
    • Increases the capacity of this ArrayList instance, if necessary, to ensure that it can hold at least the number of elements specified by the minimum capacity argument.
  • void trimToSize()
    • Trims the capacity of this ArrayList instance to be the list's current size. An application can use this operation to minimize the storage of an ArrayList instance.
polygenelubricants
+13  A: 

I'm curious, what do you need it for? You should know that the capacity is not (as it may sound) an upper limit of how much you can put into the ArrayList. It's a value representing how much data you can put into the list, without forcing it to reallocate it internal array. Basically, the notion of capacity is only there in order for you to tweak the performance slightly.

Anyway, perhaps you already know that, so here comes the actual answer.

The interface provided by API for ArrayList simply doesn't support such use case. There are many reasons for this. One reason is that you shouldn't care about this. The ArrayList is to be thought of as an unbounded array which abstracts away from details such as capacity.

The closest you can get to controlling the capacity is through the constructor ArrayList(int initialCapacity), and the two methods trimToSize() and ensureCapacity(int minCapacity).

For fun however, I managed to solve it through an ugly reflection-hack (don't use this):

import java.lang.reflect.Field;
import java.util.ArrayList;
public class Test {

    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<Integer>(3);
        for (int i = 0; i < 17; i++) {
            list.add(i);
            System.out.format("Size: %2d, Capacity: %2d%n",
                              list.size(), getCapacity(list));
        }
    }

    static int getCapacity(ArrayList<?> l) throws Exception {
        Field dataField = ArrayList.class.getDeclaredField("elementData");
        dataField.setAccessible(true);
        return ((Object[]) dataField.get(l)).length;
    }
}

Output:

Size:  1, Capacity:  3
Size:  2, Capacity:  3
Size:  3, Capacity:  3
Size:  4, Capacity:  5
Size:  5, Capacity:  5
Size:  6, Capacity:  8
Size:  7, Capacity:  8
Size:  8, Capacity:  8
Size:  9, Capacity: 13
Size: 10, Capacity: 13
Size: 11, Capacity: 13
Size: 12, Capacity: 13
Size: 13, Capacity: 13
Size: 14, Capacity: 20
Size: 15, Capacity: 20
Size: 16, Capacity: 20
Size: 17, Capacity: 20
aioobe
I am tempted to vote this down, even 'though it is correct, in-depth and warns of the dangers of trying to circumvent it, just because it provides code for the ugly hack ...
Joachim Sauer
Sure, it should be emphasized that this method should not be used in production code. It *could* however be the case that someone wishes to, for instance, debug some performance issue or similar, in which case the above code-snippet may be useful. But as I wrote in the answer, I implemented it for fun and it shouldn't really be used in 99% of the cases.
aioobe
@aiobee nice hack :) To make your answer more complete I would suggest you to also mention the java sdk/jvm you used. Since the successful working of this would be based on implementation of java platform you are using.
Gopi
@Gopi, because of the string "elementData"? I don't think the specific JVM matters, but for reference I used Hotspot and Suns 1.6.0.20 rt.jar.
aioobe
@aiobee yes because of 'elementData'. I think its quite possible that all implementations of ArrayList may not have this field or this field with same name.
Gopi
@Gopi. You're absolutely right. Since it is a private variable, nothing in the api specifies the actual name. If it would have had a package, public or protected scope, things would be different :-)
aioobe
A: 

I'm going to buck the trend here...the user has a question albeit with no context. Without context, knowing the capacity is unnecessary as the backing array will grow to accommodate...

You can do the following to know for certain what the capacity is with your ArrayList. The side effect is the backing array will be trimmed to the exact number of elements in the array:

ArrayList list = new ArrayList();
//add a bunch of elements
list.trimToSize();
System.out.println("Capacity = " + list.size());

Enjoy!

T Reddy
A: 

In JavaDoc they have clearly mentioned

Each ArrayList instance has a capacity. The capacity is the size of the array used 
to store the elements in the list. It is always at least as large as the list 
size. As elements are added to an ArrayList, its capacity grows automatically. 
The details of the growth policy are not specified beyond the fact that adding 
an element has constant amortized time cost.

Also you can ensure capacity using

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.
VinAy