I'm getting periodic crash reports on the following line of code:
myList.get(myList.size() - 1)
Which wouldn't be that interesting if not for the stack trace:
java.lang.ArrayIndexOutOfBoundsException: length=22; index=-1
java.util.ArrayList.get ArrayList.java:439
com.myapp.ope.api.ApiManager$2.onResponse ApiManager.java:215
retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1 DefaultCallAdapterFactory.java:89
retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$hVGjmafRi6VitDIrPNdoFizVAdk.run Unknown Source:6
Which seems to imply myList
has a length of 22. So how is the index calculated at -1 (which means .size()
would have reported 0)?
CodePudding user response:
ArrayList is backed by an array internally and it dynamically adjusts internal array as needed and size variable is maintained as you add elements ( increments as you add elements and decrements as you delete elements).
say at some point underlying array of ArrayList is with the length 22 (could be empty array, i.e. no elements stored), when you try to access it with -1 index, it will throw the java.lang.ArrayIndexOutOfBoundsException
*try printing list size before accessing the list as well to see if the size is coming as 0 or not
CodePudding user response:
Property length
indicates array's allocated memory
.
Size
indicates number of elements
in Array.
When we run out of allocated memory java copies current array into new array with even more allocated memory. This will be repeated every time when we fill allocated memory of Array.
Official documentation provides more descriptive explanation.
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.