This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get the capacity of the ArrayList in Java?
How to find the capacity of an ArrayList?
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
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().
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.
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.
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().
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!
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.
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.
Related
This question already has answers here:
Distinction between the capacity of an array list and the size of an array
(7 answers)
In Java 8, why is the default capacity of ArrayList now zero?
(6 answers)
Closed 5 years ago.
As per the Java API the default capacity for a java.util.ArrayList is 10.
public ArrayList()
Constructs an empty list with an initial capacity of ten.
I created a list without specifying the initial capacity as below and found that the initial capacity is 0 for the list.
ArrayList<String> list = new ArrayList<String>();
ArrayList<String> list50 = new ArrayList<String>(50);
list.add("1");
list50.add("2");
System.out.println(list.size());
I know i am making some silly mistake in interpretation, please correct me.
The initial capacity of a newly instantiated ArrayList is 0 - for performance reasons, an empty ArrayList uses a shared default array of size 0, so that if no new items are added to the list, you don't pay for allocating a new array that is never used.
Once the first item is added, the DEFAULT_CAPACITY (which is 10) is then used, i.e. the ArrayList creates a new array with size 10, which will then hold the first item (and has 9 additional, empty slots).
So I think you indeed used a slightly mistaken interpretation of the documentation.
The initial capacity is 0, and is then increased to 10 upon adding the first item, in order to avoid immediate reallocation for adding the next subsequent 9 items.
size and capacity are not the same...
every time you call add, ArrayList invoke ensureCapacityInternal, there you can find DEFAULT_CAPACITY which is 10 as you pointed....
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
so this statement
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
increase the capacity to 10 after the 1st insertion
As I recall, before Java 8, the default capacity of ArrayList was 10.
Surprisingly, the comment on the default (void) constructor still says: Constructs an empty list with an initial capacity of ten.
From ArrayList.java:
/**
* Shared empty array instance used for default sized empty instances. We
* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
* first element is added.
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
...
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
Technically, it's 10, not zero, if you admit for a lazy initialisation of the backing array. See:
public boolean add(E e) {
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
where
/**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10;
What you're referring to is just the zero-sized initial array object that is shared among all initially empty ArrayList objects. I.e. the capacity of 10 is guaranteed lazily, an optimisation that is present also in Java 7.
Admittedly, the constructor contract is not entirely accurate. Perhaps this is the source of confusion here.
Background
Here's an E-Mail by Mike Duigou
I have posted an updated version of the empty ArrayList and HashMap patch.
http://cr.openjdk.java.net/~mduigou/JDK-7143928/1/webrev/
This revised implementation introduces no new fields to either class. For ArrayList the lazy allocation of the backing array occurs only if the list is created at default size. According to our performance analysis team, approximately 85% of ArrayList instances are created at default size so this optimization will be valid for an overwhelming majority of cases.
For HashMap, creative use is made of the threshold field to track the requested initial size until the bucket array is needed. On the read side the empty map case is tested with isEmpty(). On the write size a comparison of (table == EMPTY_TABLE) is used to detect the need to inflate the bucket array. In readObject there's a little more work to try to choose an efficient initial capacity.
From: http://mail.openjdk.java.net/pipermail/core-libs-dev/2013-April/015585.html
In java 8 default capacity of ArrayList is 0 until we add at least one object into the ArrayList object (You can call it lazy initialization).
Now question is why this change has been done in JAVA 8?
Answer is to save memory consumption. Millions of array list objects are created in real time java applications. Default size of 10 objects means that we allocate 10 pointers (40 or 80 bytes) for underlying array at creation and fill them in with nulls.
An empty array (filled with nulls) occupy lot of memory .
Lazy initialization postpones this memory consumption till moment you will actually use the array list.
Please see below code for help.
ArrayList al = new ArrayList(); //Size: 0, Capacity: 0
ArrayList al = new ArrayList(5); //Size: 0, Capacity: 5
ArrayList al = new ArrayList(new ArrayList(5)); //Size: 0, Capacity: 0
al.add( "shailesh" ); //Size: 1, Capacity: 10
public static void main( String[] args )
throws Exception
{
ArrayList al = new ArrayList();
getCapacity( al );
al.add( "shailesh" );
getCapacity( al );
}
static void getCapacity( ArrayList<?> l )
throws Exception
{
Field dataField = ArrayList.class.getDeclaredField( "elementData" );
dataField.setAccessible( true );
System.out.format( "Size: %2d, Capacity: %2d%n", l.size(), ( (Object[]) dataField.get( l ) ).length );
}
Response: -
Size: 0, Capacity: 0
Size: 1, Capacity: 10
Article Default capacity of ArrayList in Java 8 explains it in details.
If the very first operation that is done with an ArrayList is to pass addAll a collection which has more than ten elements, then any effort put into creating an initial ten-element array to hold the ArrayList's contents would be thrown out the window. Whenever something is added to an ArrayList it's necessary to test whether the size of the resulting list will exceed the size of the backing store; allowing the initial backing store to have size zero rather than ten will cause this test to fail one extra time in the lifetime of a list whose first operation is an "add" which would require creating the initial ten-item array, but that cost is less than the cost of creating a ten-item array that never ends up getting used.
That having been said, it might have been possible to improve performance further in some contexts if there were a overload of "addAll" which specified how many items (if any) would likely be added to the list after the present one, and which could use that to influence its allocation behavior. In some cases code which adds the last few items to a list will have a pretty good idea that the list is never going to need any space beyond that. There are many situations where a list will get populated once and never modified after that. If at the point code knows that the ultimate size of a list will be 170 elements, it has 150 elements and a backing store of size 160, growing the backing store to size 320 will be unhelpful and leaving it at size 320 or trimming it to 170 will be less efficient than simply having the next allocation grow it to 170.
The question is 'why?'.
Memory profiling inspections (for example (https://www.yourkit.com/docs/java/help/inspections_mem.jsp#sparse_arrays) shows that empty (filled with nulls) arrays occupy tons of memory .
Default size of 10 objects means that we allocate 10 pointers (40 or 80 bytes) for underlying array at creation and fill them in with nulls. Real java applications create millions of array lists.
The introduced modification removes^W postpone this memory consumption till moment you will actually use the array list.
After above question I gone through ArrayList Document of Java 8. I found the default size is still 10 only.
ArrayList default size in JAVA 8 is stil 10. The only change made in JAVA 8 is that if a coder adds elements less than 10 then the remaining arraylist blank places are not specified to null. Saying so because I have myself gone through this situation and eclipse made me look into this change of JAVA 8.
You can justify this change by looking at below screenshot. In it you can see that ArrayList size is specified as 10 in Object[10] but the number of elements displayed are only 7. Rest null value elements are not displayed here. In JAVA 7 below screenshot is same with just a single change which is that the null value elements are also displayed for which the coder needs to write code for handling null values if he is iterating complete array list while in JAVA 8 this burden is removed from the head of coder/developer.
Screen shot link.
I want to solve this question
1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB
Here is my code
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static String convertToTitle(int n) {
if(n<=0)
return null;
List temp=new ArrayList();
int i=0;
while(n!=0)
{
int residual=0;
residual=n%26;
n=n/26;
temp.add((char)(residual-1+'A'));
i++;
}
char[] temp_final=new char[i];
for(int j=0; j<i-1;j++)
temp_final[j]=(char)(temp.remove(j));
return String.valueOf(temp_final);
}
public static void main(String[] args) {
String test;
test=Solution.convertToTitle(2);
System.out.println(test);
}
}
The result is null. I do not know the reason. When I debug with Eclipse, I find the size of temp shows 1, but in the elementData Object shows 10 elements.The first element is B, the other nine are null. Why is it 10 rather 1? Is it due to this?
This the image of variables when debugging
enter image description here
Why is it 10 rather 1?
Because that is the way that ArrayList works!
An array list stores the list in a backing array (elementData).
When you create an ArrayList with new ArrayList(), the initial backing array size will be 10. (Refer to the source code; e.g. here.)
Why did they do this?
It is all about maintaining this guarantee stated in the javadoc:
"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."
The way that this is achieved is to start the backing array with a reasonable "initial capacity", and grow the array exponentially when it fills up. The exact details vary with Java version.
Hypothetically, the ArrayList class could use a backing array that is the same size as the list size. But that gives terrible performance. Each time you added an element to the list you would need to "grow" the backing array. That entails allocating a new array with size 1 greater than the current size, and then copying the existing elements one at a time to the new array. If you do the math, appending an element to a list of size N involves copying N existing element references ... making the append operation O(N).
An ArrayList is a List implementation using an array to store the elements.
At any point in time, a List has a size(), i.e. the number of elements in the list. For an ArrayList, those elements are stored in a single array with a length that is greater than or equal to the size() (can't very well be less than size(), right?)
The array length is called the capacity of the ArrayList, i.e. the number of elements the ArrayList can handle without having to re-size the array.
The debugger shows the size and the elementData array, but only the first size values of the array are "in the list".
By default, a new ArrayList has an initial capacity of 10. In Java 8, the backing array will be increased in size in 50% chunks when needed, i.e. 10, 15, 22, 33, 49, 73, 109, ...
If you know you're going to add 1000 elements to an ArrayList, you can specify the initial capacity on the constructor. That prevents the need for continually resizing the array as the 1000 elements are added (performance boost).
Suppose there are 10 elements in ArrayList and if i have deleted 2 elements from the middle , so the arraylist will contain 8 elements , but will the capacity be 10 or reduced to 8 at that time.
The API states :
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.
and you can always test this empirically in your debugger. After removing two elements, look at the array that backs the ArrayList, and see what it's size is. Most likely, it's 10.
The behaviour depends on the implementation of the ArrayList. You can't rely on this kind of implementation details. The only thing you must consider is that the capacity is always greater or equal to the number of elements in your list. If you need the capacity to be exactly the number of elements (because you may want to reduce memory usage), you will have to ask it explicitly with the function trimToSize().
I think it may change because suppose we create new array list by default JVM allocate say 10 continuous locations in memory .if you put 8 or 2 or zero it will be same .
But is you put 15 element then it will increase it to say 20 memory locations .But if you below 10 again it should release that memory and reduce to 10 default size .
This is dynamic allocation .For 1000 element list if you are removing the element and reduce to 2 then it is logical that it must release that memory .It should depend on number of elements removed.
When I learned Java, I was told that the arraylist works this way:
It creates an array with room for 10 elements.
When the 11th element is added, it is created a new list with room for 20 elements, and the 10 elements are copied into the new array. This will repeat as until there are no more elements to add, or to a maximum size.
Is the List in .NET constructed the same way?
You can easily test this by querying a List's Capacity:
var a = new List<string>();
Console.WriteLine(a.Capacity); // Writes 0
a.Add("abc");
Console.WriteLine(a.Capacity); // Writes 4
a.Add("abc");
a.Add("abc");
a.Add("abc");
a.Add("abc");
Console.WriteLine(a.Capacity); // Writes 8
So it doesn't allocate any room at all upon instantiation, but upon first added item. From 8 it grows to 16, 32, etc...
The generic List type doubles its internal array length every time the current array is filled up.
MSDN Link
The details are a bit different (in terms of the default number of elements and how it expands), but essentially it is the same.
I believe that's how it works, yes. I can't find any documentation at the moment that tells you the exact algorithm they use, but there is definitely the concept of Capacity (size of the "internal" array) and Count (the actual number of elements you've added).