android arraylist 长度限制,java - Android Arraylist Size() anomaly - Stack Overflow

It's always important to remember that List is just an interface. It contains all the methods which you would expect from a List but there is no default implementation for it. There are multiple classes that implement this List interface and they have different strategies on how to implement it. For example:

ArrayList: Uses an array to store the elements.

LinkedList: Holds two references for each element in the list, one to the previous item and one to the next item.

Vector: Also uses an array internally, but all operations are synchronised and therefore thread-safe.

Stack: Subclass of Vector, but uses a LIFO (Last In, First Out) data structure.

You are asking why even though size() returns 15 there are 18 elements in the ArrayList when you look at it with the debugger. This is a consequence of how the ArrayList is implemented, as I told you above there is no such thing as a List, the ArrayList is just a wrapper around an array.

You might ask now: "But why is it bigger in the first place?". The answer to that is one simple thing: Performance. To understand the reason you just have to imagine what happens internally in an ArrayList when you add items, I will demonstrate this with a few lines of pseudo code.

Think about when the ArrayList is created:

ArrayList list = new ArrayList();

The ArrayList does not know at this point how many elements will be added to it, so what is happening internally to the array? When we declare an array it has to have a size, so some arbitrary size is picked, maybe 4:

String[] array = new String[4];

In reality the ArrayList will probably pick a number larger than 4 initially. This is just for demonstration purposes. So what we have now is an ArrayList with 0 items in it, but the array it uses to save those items has already a size of 4. If you looked at it with a debugger at this time you would see 4 spots in the array of the ArrayList, but all would be null. If you called size() now it would return 0. Because there are no items in the ArrayList. That there are 4 spaces in the array has nothing to do with amount of items actually stored.

So now we begin to add items, maybe the letters "a" up to "e":

list.add("a");

list.add("b");

list.add("c");

list.add("d");

list.add("e");

Internally it just assigns this object to one free space in the array, first the "a":

array[0] = "a";

So after adding "a" we have it at the first position in our array, but the other 3 places are still empty. If you were to place a breakpoint on list.add("b"); you would see that the first item in the array is "a" and the 3 spaces after that are null. If you were to call size() at this point it would return 1, because there is 1 item in the ArrayList. So we continue to add items and they are assigned to the internal array:

array[1] = "b";

array[2] = "c";

array[3] = "d";

Everything is fine until "d", but when we want to add "e" we hit a snag. We initially just picked a size of 4 for our array. So after adding "a", "b", "c" and "d" the array is full, we cannot add another item to it. What the ArrayList does in this case is create a new array with twice the size - in our case 8 because the previous size was 4 - and copies all the items from the previous array to the new one:

String[] biggerArray = new String[array.length * 2];

for(int i = 0; i < array.length; i++) {

biggerArray[i] = array[i];

}

After this there is no problem assigning "e" to a free space in the array:

biggerArray[4] = "e";

But what we again have after the adding is finished is an ArrayList with 5 elements, but the array used to save those elements has a size of 8. So again if you were to add a breakpoint after the adding is finished you would see an array with the size 8 in the ArrayList, the first 5 spots would be occupied by the letters "a", "b", "c", "d" and "e" but the remaining 3 are not currently used and would be null. If you called size() at this point it would return 5, because there are 5 elements in the ArrayList. Again size() has nothing to do with the size of the array used to store the elements, but returns the actual amount of items in the ArrayList.

Conclusion:

And finally we come to the point I was trying to make and why this is all a performance issue:

If we can just resize the array why is it not the always exactly the size of the items in it and resized only when we add an additional item? Because as I should above, each time the array has to be resized you need to copy all the items from the old array to the new one. This can be an expensive and time consuming process, especially when you have hundreds or maybe even thousands of items in the ArrayList. So at the start some arbitrarily large size for the array is picked and then every time the array fills up it is doubled in size, hoping that this doubling in size is enough to not have to resize it again any time soon, leaving half the places in the array filled with an item and all the others empty.

As you might already have noticed you can among other things pass a capacity to the ArrayList in its constructor:

ArrayList list = new ArrayList(100);

If you do this than the internal array will already be initialised with the capacity you want. This is for the case that you already know or at least have a vague idea how many items you are going to add to the ArrayList. By doing this you can prevent the internal resizing of the array and items can be added to the ArrayList a lot quicker! This is also a great way to see the effects of the ArrayList being internally an array. Initialise an ArrayList like above with a capacity 100 and when you add a breakpoint after that you will see that the internal array has a length of 100.

If you have any further questions, feel free to ask!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值