Iterating over an ArrayList efficiently is one of the most frequent operations in Java development. Whether you need element access, filtering, or transformation, this guide provides modern and legacy techniques to loop over an ArrayList safely, performantly, and with best-practice patterns used in enterprise systems.
This updated guide on javatechig.com covers all iteration strategies for Java 8 and later, including lambda-style loops, iterators, and classic control structures.
What Is an ArrayList in Java?
An ArrayList is a resizable array implementation of the List interface from the Java Collections Framework. Unlike arrays, it grows dynamically and offers convenient utility methods.
Typical use cases include:
- Dynamic data collections
- CRUD operations
- Sorting & searching
- Iterations for rendering or processing
1. Classic for Loop
The traditional for loop gives precise control using index access.
List<String> list = new ArrayList<>(Arrays.asList("Java", "Kotlin", "Python"));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
This works in all Java versions and gives index-based access.
2. Enhanced for Loop (For-Each)
Introduced to simplify iteration:
for (String item : list) {
System.out.println(item);
}
This is the most readable and common pattern when index is not needed.
3. Using Iterator
An Iterator safely traverses collections and supports removal while iterating.
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
Use this to avoid ConcurrentModificationException when removing elements.
4. Using ListIterator
ListIterator supports bi-directional traversal and modification.
ListIterator<String> listIt = list.listIterator();
while (listIt.hasNext()) {
System.out.println(listIt.next());
}
while (listIt.hasPrevious()) {
System.out.println(listIt.previous());
}
This is useful when you need reverse traversal or element updates.
5. Java 8 forEach Loop
The forEach() method allows lambda-style processing:
list.forEach(item -> System.out.println(item));
This improves readability and is preferred in modern Java.
6. Stream API for Iteration
Streams support functional processing and bulk operations:
list.stream()
.forEach(System.out::println);
You can also filter, map, and collect results as part of iteration.
7. Parallel Streams (Advanced)
For concurrent processing:
list.parallelStream()
.forEach(System.out::println);
Use parallel streams when reading is heavy and your workload is multi-core optimized.
8. Removing Elements Safely
Using Iterator:
Iterator<String> it = list.iterator();
while (it.hasNext()) {
if ("Python".equals(it.next())) {
it.remove();
}
}
Avoid removing elements directly inside an enhanced for loop to prevent runtime errors.
9. Performance Considerations
- Classic for and enhanced for: fastest for in-memory lists
- Iterator: safe modification and stable iteration
- Stream: expressive, slightly higher overhead
- ParallelStream: good for large data sets
Benchmark according to real usage patterns for large collections.
When to Choose Which Loop
| Use Case | Best Approach |
|---|---|
| Simple iteration | Enhanced for |
| Index based processing | Classic for |
| Safe removal | Iterator |
| Reverse traversal | ListIterator |
| Functional transformation | Stream / forEach |
| Parallel data processing | ParallelStream |
Common Mistakes
1. Modifying List During Enhanced For
Removing inside enhanced for causes ConcurrentModificationException. Use Iterator.
2. Large List Iteration on UI Threads
Avoid heavy iterations on the main thread in Android or GUI apps.
Best Practices (2026 Updated)
- Use lambda
forEachfor concise code - Use streams for transformations
- Use iterators when safe removal is needed
- Benchmark large loops for performance
- Avoid modifying list while iterating


