My Problem
I have a fixed-size ArrayList which contains custom variables. Despite of the ArrayList having a fixed size, sometimes a lot of them will actually be null. The thing is that I need to return the ArrayList without the null variables inside it. One important thing to note: the ArrayList will have all of its non-null items first, and then all of the nulls below them, e.g., the elements are not mixed. Example: [non-null, non-null, .... null, null, null]
My workaround
I though of creating a for-loop that checked (from last to first index) each of the elements inside the ArrayList to determine if it's null or not. If is null, then I'd call this code:
for (i = size-1; i >=0 ; i--) {
groupList = new ArrayList<>(groupList.subList(0, i));
}
My question
If the ArrayList is too big, this method might me particularly slow (or not?). I was wondering if there exists a better, more performance-friendly solution. AFAIK the .subList method is expensive.
ArrayList. subList() method. This method takes two parameters i.e. the start index for the sub-list(inclusive) and the end index for the sub-list(exclusive) from the required ArrayList. If the start index and the end index are the same, then an empty sub-list is returned.
import org. List<Integer> inputList = new ArrayList(Arrays. asList(100, 101, 102, 103, 104, 105)); /* Change the value of chunkSize to get desired number of elements in each of the partitionedList */ int chunkSize = 5; List<List<Integer>> partitionedList = ListUtils. partition(inputList, chunkSize);
Why is ArrayList so much slower? Because an ArrayList has a distinct array object inside of it. Operations typically involve extra indirections (e.g. to fetch the list's size and inner array) and there are extra bounds checks (e.g. checking the list's size and the array's length).
You can have a variant of binary search, where your custom comparator is:
You are looking for the first null element.
This will take O(logn) time, where n
is the size of the array.
However, taking the sublist of the ArrayList
that is none null (assuming you are going to copy it to a new list object), is going to be linear time of the elements copied, since you must "touch" each of them.
This gives you total time complexity of O(logn + k)
, where k
is number of non null elements, and n
is the size of the array.
Following all of your outstanding advices, I modified the original method so that I can take the last (first) ever null item position and call the .subList method just once. And here it is:
int lastNullIndex = size - 1;
for (i = lastNullIndex; i >= 0; i--) {
if (null == groupList.get(i)) {
lastNullIndex = i;
} else {
break;
}
}
groupList = new ArrayList<>(groupList.subList(0, lastNullIndex));
return groupList;
If you think it can be further modified so as to allow for a better performance, let us know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With