Now that we have made our ArrayList, it is time to traverse the ArrayList! To traverse an ArrayList, we can use the same two methods that we use to traverse regular arrays: using the regular for loop and the enhanced for loop.
There are only two differences in the for loop implementation.
Instead of using bracket notation, we use get().
We use size() for the ArrayList instead of the length variable.
Like with regular array traversals using for loops, if you try to access an index outside of the range of the ArrayList, you'll get a IndexOutOfBoundsException
.
Here is an example of the for loop implementation:
public static void forTraversal(ArrayList<E> list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
The enhanced for loop code is basically unchanged. Here is an example of the enhanced for loop implementation:
public static void enhancedForTraversal(ArrayList<E> list) {
for (E element: list) {
System.out.println(element);
}
}
As with arrays, we can only change the items in an ArrayList using set(), and not by changing the enhanced for loop variable, as Java is a pass-by-value language. However, as before, we can change instance variables of objects inside ArrayLists using an enhanced for loop.
Sometimes we want to remove elements while traversing the ArrayList. This can only be done with the regular for loop. Changing the size of an ArrayList (either by adding or removing elements) while using an enhanced for loop will result in a ConcurrentModificationException
.
When deleting an element at an index i, remember that the element that used to be at index i+1 (the next element) is now at index i. This will require us to do an i-- before the loop incrementation to avoid skipping an element.
The size() in the loop condition will automatically change as you add or remove items, so we don't need to worry about it not being accurate or the method crashing. Here is a method that removes all even numbers from an ArrayList like integerList above:
/** Removes all even numbers
*/
public static ArrayList<Integer> removeEvens(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0) {
list.remove(i);
i--;
}
}
}
Other times, we may want to add elements to an ArrayList during traversal. However, this brings up its own problem. Let's take a look:
Let's have a method that inserts a 1 at index i, if the element at i is equal to 4.
At some index i, the element is 4, so 1 is now added at index i.
That 4 is now at index i+1.
i is incremented, so the current index being checked is i+1.
At index i+1, the element is 4, so steps 2-4 are repeated, causing an infinite loop!
To avoid an infinite loop, we increment i before the loop incrementation so that i++ occurs twice and the loop checks the actual next item. Let's see this by duplicating all odd numbers in an ArrayList like integerList:
/** Duplicates all odd numbers
*/
public static ArrayList<Integer> duplicateOdds(ArrayList<Integer> list) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 1) {
list.add(i, list.get(i));
i++;
}
}
}