This question already has answers here:
Why start an ArrayList with an initial capacity?
(11 answers)
Closed 2 years ago.
According to a book I was reading
There is an important distinction between the capacity of an array list
and the size of an array. If you allocate an array with 100 entries,
then the array has 100 slots, ready for use. An array list with a
capacity of 100 elements has the potential of holding 100 elements
(and, in fact, more than 100, at the cost of additional reallocations)—
but at the beginning, even after its initial construction, an array list
holds no elements at all.
However, we can also create an ArrayList without any capacity defined.
How will an ArrayList without any capacity defined and an ArrayList with capacity allocate its elements and when we should use one over the other?
The only thing striking my mind is, why would we have capacity if in both ways (ArrayList with capacity and ArrayList with no capacity), the values will be treated same way, so the only possible reason coming in my mind is that they both hold values differently.
The reason for providing an initial allocation is to pre-allocate the memory representation required to hold that many items, otherwise dynamic allocation is necessary for all item added. Note, dynamic allocation becomes necessary once the array contains the number of pre-allocated items.
Related
This question already has answers here:
Performance differences between ArrayList and LinkedList [duplicate]
(11 answers)
When to use LinkedList over ArrayList in Java?
(33 answers)
Closed 1 year ago.
This post was edited and submitted for review 4 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Yesterday I ran a benchmark in Java 17 where I repeatedly created a new Arraylist and Linkedlist and added 10.000.000 Elements to it.
By the nature of a LinkedList adding elements (creating a LinkedObject an putting it at the end) should be much faster than adding to an ArrayList. (Copying whole array in anotherone that is slightly larger.)
Are native functions like arraycopy() really that much faster? The only thing the LinkedList was better at was merging two LinkedLists together.
Most of the time, adding to an ArrayList won't allocate a new array, since the implementation increases the size of the backing array by 50% when it needs to grow.
This may sound wasteful from a memory perspective, but even a worst-case scenario for a growing ArrayList uses less memory than LinkedList - each entry in a linked list costs an object header + 3 references (prev/value/next), whereas a worst-case growing ArrayList has only 1.5 references per entry (i.e., the array cells used, plus 50% which are as-yet unused).
Anywho, according to my calculations, this means that adding 10 million entries to a default-initiated ArrayList will result in some 35 array-copying actions, which isn't very much. (And yes, System.arraycopy is fast.)
Finally, if you give your array an initial capacity of 10_000_000, there will be zero array copies made. You can try that to see how much the copying really costs.
This question already has answers here:
Does the capacity of ArrayList decrease when we remove elements?
(7 answers)
Closed 3 years ago.
If you have an Array List that has been extended (the array has grown) to contain many elements and these elements are then removed, does the actual array size change to save memory?
In more details, when removing an element from a large Array List, is the reserved memory for the array empty part of the array recovered? It would seem logic that since we expanded the array we might need to use this space and so it will not be touched.
However if we have a really large array list and we only use the first 10 or so elements, will the compiler (or on run time) realize that all the extra space is being wasted and recover it? (Will the actual array size be decreased? (Copying the elements into a smaller array?))
You can call trimToSize() in order to replace the backing array of the ArrayList with a smaller array that matches the size of the list.
void java.util.ArrayList.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.
This question already has answers here:
When to use LinkedList over ArrayList in Java?
(33 answers)
Closed 7 years ago.
In my java app deployed on tomcat, about 500K items (can go even upwards) are
added to ArrayList.
Then, these list(s) are iterated to check some conditions.
Que- For this scenario, would using LinkedList gain performance?
Any pointers from practical experience for volume of data exceeding 200K items~ 1 million items.
Mostly list of strings and objects having multiple properties mostly string
(Basically get data from DB, convert it to Java objects and send it over via HTTP)
If size of data is expected to stay within 100K or less, would there be a difference
See this question:
When to use LinkedList over ArrayList?
LinkedList allows for constant-time insertions or removals using
iterators, but only sequential access of elements. In other words, you
can walk the list forwards or backwards, but finding a position in the
list takes time proportional to the size of the list.
ArrayList, on the other hand, allow fast random read access, so you
can grab any element in constant time. But adding or removing from
anywhere but the end requires shifting all the latter elements over,
either to make an opening or fill the gap. Also, if you add more
elements than the capacity of the underlying array, a new array (1.5
times the size) is allocated, and the old array is copied to the new
one, so adding to an ArrayList is O(n) in the worst case but constant
on average.
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.
I understand that capacity is the number of elements or available spaces in an ArrayList that may or may not hold a value referencing an object. I am trying to understand more about the concept of capacity.
So I have three questions:
1) What are some good ways to define what capacity represents from a memory standpoint?
...the (contiguous?) memory allocated to the ArrayList?
...the ArrayLists’s memory footprint on the (heap?)?
2) Then if the above is true, changing capacity requires some manner of memory management overhead?
3) Anyone have an example where #2 was or could be a performance concern? Aside from maybe a large number of large ArrayLists having their capacities continually adjusted?
The class is called ArrayList because it's based on an array. The capacity is the size of the array, which requires a block of contiguous heap memory. However, note that the array itself contains only references to the elements, which are separate objects on the heap.
Increasing the capacity requires allocating a new, larger array and copying all the references from the old array to the new one, after which the old one becomes eligible for garbage collection.
You've cited the main case where performance could be a concern. In practice, I've never seen it actually become a problem, since the element objects usually take up much more memory (and possibly CPU time) than the list.
ArrayList is implemented like this:
class ArrayList {
private Object[] elements;
}
the capacity is the size of that array.
Now, if your capacity is 10, and you're adding 11-th element, ArrayList will do this:
Object[] newElements = new Object[capacity * 1.5];
System.arraycopy(this.elements, newElements);
this.elements = newElements;
So if you start off with a small capacity, ArrayList will end up creating a bunch of arrays and copying stuff around for you as you keep adding elements, which isn't good.
On the other hand, if you specify a capacity of 1,000,000 and add only 3 elements to ArrayList, that also is kinda bad.
Rule of thumb: if you know the capacity, specify it. If you aren't sure but know the upper bound, specify that. If you just aren't sure, use the defaults.
Capacity is as you described it -- the contiguous memory allocated to an ArrayList for storage of values. ArrayList stores all values in an array, and automatically resizes the array for you. This incurs memory management overhead when resizing.
If I remember correctly, Java increases the size of an ArrayList's backing array from size N to size 2N + 2 when you try to add one more element than the capacity can take. I do not know what size it increases to when you use the insert method (or similar) to insert at a specific position beyond the end of the capacity, or even whether it allows this.
Here is an example to help you think about how it works. Picture each space between the |s as a cell in the backing array:
| | |
size = 0 (contains no elements), capacity = 2 (can contain 2 elements).
|1| |
size = 1 (contains 1 element), capacity = 2 (can contain 2 elements).
|1|2|
size = 2, capacity = 2. Adding another element:
|1|2|3| | | |
size increased by 1, capacity increased to 6 (2 * 2 + 2). This can be expensive with large arrays, as allocating a large contiguous memory region can require a bit of work (as opposed to a LinkedList, which allocates many small pieces of memory) because the JVM needs to search for an appropriate location, and may need to ask the OS for more memory. It is also expensive to copy a large number of values from one place to another, which would be done once such a region was found.
My rule of thumb is this: If you know the capacity you will require, use an ArrayList because there will only be one allocation and access is very fast. If you do not know your required capacity, use a LinkedList because adding a new value always takes the same amount of work, and there is no copying involved.
1) What are some good ways to define what capacity represents from a memory standpoint?
...the (contiguous?) memory allocated to the ArrayList?
Yes, an ArrayList is backed up by an array, to that represents the internal array size.
...the ArrayLists’s memory footprint on the (heap?)?
Yes, the larget the array capacity, the more footprint used by the arraylist.
2) Then if the above is true, changing capacity requires some manner of memory management overhead?
It is. When the list grows large enough, a larger array is allocated and the contents copied. The previous array maybe discarded and marked for garbage collection.
3) Anyone have an example where #2 was or could be a performance concern? Aside from maybe a large number of large ArrayLists having their capacities continually adjusted?
Yes, if you create the ArrayList with initial capacity of 1 ( for instance ) and your list grows way beyond that. If you know upfront the number of elements to store, you better request an initial capacity of that size.
However I think this should be low in your list of priorities, while array copy may happen very often, it is optimized since the early stages of Java, and should not be a concern. Better would be to choose a right algorithm, I think. Remember: Premature optimization is the root of all evil
See also: When to use LinkedList over ArrayList