ArrayList trimtosize not working android - java

Am having an arraylist and its code is:
ArrayList<String> recentdata=new ArrayList<String>();
I want to limit the size of ArrayList to a specific size i.e. 5 in my case, when it reaches to that number.
That means 0 to 5 it works as ArrayList, when it reaches to that 5, I want to stop the growth of ArrayList.
For that am using: to set the size
if(recentdata.size() >= 5) {
recentdata.trimToSize();
}
but its not working i.e., size growth is not stopping it goes 6,7 etc.
How to do this? anyother way to do this? or what is wrong in my approach?
Thanks

Size and capacity are two different things.
Say you have this:
ArrayList<String> data = new ArrayList<String>(5);
Your capacity is 5, but the size is 0.
Then you add some data:
data.add("hello");
Then you call trimToSize:
data.trimToSize();
Your size and capacity are both now 1.
What exactly are you trying to do? There is probably a better way to do it :)

trimToSize doesn't remove any element from the list. From the javadoc:
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.
The capacity is the size of the array used by the ArrayList internally. If your list contains 6 elements and has a capacity of 10, the last 4 elements of the array are null. Calling trimToSize will just make the list use an array of 6 instead of 10.
Just don't add anything to the list once its size is 5, instead of adding, and then trying to remove.

Related

Why we can't add element into a List to nth index before adding element to (n-1)th index even if initial capacity is provided

Suppose I declare an array of int with size 10, I can add an element to its 4th index, I can run the code without any exception.
int[] ar = new int[10];
ar[4] = 8;
System.out.println(Arrays.toString(ar)); //works fine
That's because when I say size as 10, that much memory space will be allocated for that array with initial value of its type kept in each index.
But the case is not same in List. Say I declare a list with an initial capacity of 10 and I try to add an element to its 4th index it gives
java.lang.IndexOutOfBoundsException: Index: 4, Size: 0
List<Integer> list = new ArrayList<Integer>(10);
list.add(4, 8); //exception
Of course the size of the list will return 0 even if initial capacity is given. Why is it not like Array, I think no memory is allocated for 10 elements for the list?
I was guessing that is there any way to fill List with default values once a capacity is given just like an array.
This is what the JavaDoc for ArrayList says about add(int index, E element):
throws IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
The size is the number of elements currently stored, not the current capacity.
The fact that your car has the "capacity" to drive with 100 mph, that doesn't mean that you can magically get from 0 to 90 mph within 1 second ;-)
In other words: the answer is that size and capacity aren't the same. Capacity merely means: "that is the size this list can grow to before the underlying array needs to grow".
By now it should be clear that the initial capacity on the constructor is just a bit of memory management for the initial internal array. Without any semantical meaning.
When the actual size() overflows the array, the array is reallocated.
There is no such thing as a bulk allocation with initial elements. However there is:
List<Integer> list = Collections.nCopies(10, Integer.valueOf(0));
And the new Stream offers ways to dynamically generate lists.
You could do:
public <T> void add(List<T> list, int i, T obj) {
while (list.size() < i) {
list.add(null);
}
list.add(i, obj);
}
But it is immediately evident, that you'll introduce nulls which is unsafe and ugly,
requiring null checks.
As others have mentioned in their answers, in List<Integer> list = new ArrayList<Integer>(10), the 10 specifies the initial capacity.
Specifying the initial capacity is only an optional thing. You exercise that option only when you use the particular constructor that accepts an initial capacity as an argument. When you use other constructors, you don't have control over the initial capacity.
You specify n as the initial capacity if you want the first n additions to the list to be as efficient as possible -- otherwise, there is a possibility that the addition of each individual item to the list results in some costly internal re-sizing and re-copying into the re-sized internal area.
The above does not answer the question of why you are not allowed to add an item at position 8, when there is no item at position 7.
As some have answered, that's because the API doc says so.
That's one way to answer it. But why does the API doc say so? Why are things designed so?
Things are designed so, because:
Adding an item at position 8, when there is no item at position 7, results in a gap (before position 8).
As a programmer, you will then have to keep track of what an item's position is, among all possible positions (the full capacity). Currently, as a programmer, you only keep track of what the item's position is, among all added items. Now, wouldn't that be a programming nightmare?

Increasing Array Index without using Arraylist or Copying Elements over to another Array

I have an assignment for class that requires increasing the size of an arrays index.
The instruction mentions not to create a new array and copying the elements, calling it rather inefficient. Instead they suggest the following
"A more common strategy is to choose an initial size for the array and add elements until it is full, then double its size and continue adding elements until it is full, and so on."
I'm having trouble wrapping my head around this. How would I got about accomplishing this?
You can double the size of an array if you multiply the lenght of your current array, like this:
array = Arrays.copyOf(array, array.lenght*2);
You have to create a new array or you can do something like :
int a[] = new a[10];
a = Arrays.copyOf(a, a.length + arrayGrowNumber);
In above example you are just copying your existing array to a new array defined with large size array.
For more information please visit this link.
Initial size for the array and add elements until it is full, then
double its size and continue adding elements until it is full, and so
on.
This is statement clearly shows to use java ArrayList as this strategy is used in ArrayList.
This is how it is declared.
List<Your_DataType> lst=new ArrayList<>();
e.g.
List<Integer> lst=new ArrayList<>();
lst.add(1);
lst.add(2);
lst.add(3);
lst.get(0);// shows 1 which is at 0th location
lst.get(1);// shows 2 which is at 0th location
lst.get(2);// shows 3 which is at 0th location
Your instructions are conflicting. The "common strategy" instructions will still "create a new array and copying the elements", but will do so less often.
Say you create the array at size 20, then begin adding a total of 50 values.
After adding first 20, you create a new array of size 40 and copy values over, then continue adding to the new array.
After adding 20 more (total of 40), you create a new array of size 80 and copy values over, then continue adding to this new array.
When you've added all 50 values, you have an array of size 80, with values in the first 50 positions. You've copied the array twice.
Saying that you cannot create a new array is misleading/wrong. You have to. The "common strategy" instruction of "double its size" requires it.

In Java 8, why is the default capacity of ArrayList now zero?

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.

Populate an array with unlimited index - Java

Is there a way to populate an array with unlimited indexes in java? I just want the program to keep appending to the array without any capacity.
I declared like this:
int arrInt[] = new int[]
But it says that it is missing dimension. So how can I do it?
Array in Java is static, ie. you have to declare its size while initializing. Hence the answer is 'no' and you are getting the correct message as you have not mentioned the dimension.
No, there isn't.
ArrayList serves that purpose (i.e. an array based list whose capacity increases over time automatically when adding elements to it).
Is there a way to populate an array with unlimited indexes in java?
NO
I just want the program to keep appending to the array without any
capacity.
Need to Use ArrayList
List<Object> arr = new ArrayList<Object>();
arr.add(obj1);
arr.add(obj2);
arr.add(obj3); .. so on
I declared like this - int arrInt[] = new int[]. But it says that it
is missing dimension.
Arrays will always complain to declare the size.
In java, arrays have a maximum number of elements equal to Integer.MAX_VALUE - 5. To get around this, try using a LinkedList which has an unimited number of elements. Since this is a list, you can modify the size whenever necessary in your code. Note that ArrayList also has a max number of elements of Integer.MAX_VALUE, so LinkedList is necessary if you truly need a list of unlimited size.
Resource: http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html

Adding value to list initialize list size

I have below code:
Hashtable<Integer, List<Model>> map = new Hashtable<Integer, List<Model>>();
for (int i = 0; i < arraylistAssignment.size(); i++) {
List<Model> temp = null;
for (int j = 0; j < arraylistModel.size(); j++) {
if (arraylistAssignment.get(i).getId() == arraylistModel.get(j)
.getId()) {
if (temp == null)
temp = new ArrayList<Model>();// DEBUG POINT 1
temp.add(arraylistModel.get(j));
}// DEBUG POINT 2 AFTER ADD FUNCTION ABOVE
}
map.put(arraylistAssignment.get(i).getId(), temp);
}
In the above code at debug point 1 when when i hv intitilzed the temp variable , there the object size is 0 as showm below :
but as soon as i add i.e temp.add the size is 1 but objects create is 12 out of which 11 values are null as shown below ...i could not understand the reason for null values here can anyone plz exaplin ...m i initilzing wrong?
An ArrayList is a dynamic array, what means that it grows as elements are added. But it doesn't change its size "one by one". Its size grows a "reasonable" amount, so the operation of resizing the list is not repeated each time you add an element, because this would be inefficient.
The reason for null values is because that's how ArrayLists work on the inside. They start off with a blank array inside, and as you add things they resize themselves as they see fit. The reason the array is larger than the number of objects you put in is because it'd be highly inefficient to resize the array every time you added something, so instead the ArrayList implementers just made the inner array start off at a certain size and approximately double in size every time it needs to be resized. They track how many elements you put in by tracking a separate size variable.
So in other words, you're initializing things just fine. Don't worry about the internals of the ArrayList -- if you look at the internal size variable, you'll see that it is 1, just as you expect.
ArrayList is a data structure in the Collections framework which is built on top of arrays I.e. It's implementation is done with the help of arrays. Since size is to be defined in arrays, it initializes size to be 10 at first. When you add values, it becomes the 11th item.
Now you might wonder how is this dynamic and how it works, well when size is reached to its limit it creates a new array double the size, copies the old stuff and discards the prev array. Would recommend you to take a look at the implementation.
To the user, it looks like dynamic but when you look through debugger you would see nulls. Array STARTS at 0 to 10 which makes it 11 elements and your newly added item becomes 12th but for public api, it's still the first element.
Check here for complete implementation of ArrayList: link
From Java Dokumentation:
http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
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.
Default capacity is somehow 12 in your case, even though it should be 10.

Categories