Back to Blog
Java

Java for Loop: Syntax, Usage, and Performance

java for loop: Learn the Java for loop syntax, how it executes, and when to choose the traditional, enhanced, or iterator-based form for arrays and collections.

for loopJava iterationenhanced for loopcollection traversalloop performance
Diagram showing the three parts of a Java for loop header and its execution flow through iterations.

java for loop requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The Java for loop is a control flow statement that repeats a block of code while a condition remains true. Its header contains three expressions separated by semicolons: an initialization, a condition, and an update.

for (int i = 0; i < 5; i++) { System.out.println(i); }

The initialization expression runs exactly once before the first iteration. The condition is evaluated before every iteration, including the first. If it evaluates to true, the loop body executes; if false, the loop terminates immediately. The update expression runs after the body completes, before the next condition check. This ordering matters when you rely on the loop variable's value inside the body.

The scope of the loop variable is limited to the for statement. You cannot reference i after the loop ends, which prevents accidental reuse of a stale index.

Iterating Over Arrays and Collections

The most common use of the Java for loop is walking through arrays and collection types. Arrays expose a length field, while List instances expose a size() method. Mixing these up is a frequent compile-time error.

int[] values = {10, 20, 30}; for (int i = 0; i < values.length; i++) { System.out.println(values[i]); }
List<String> cities = new ArrayList<>(List.of("Tokyo", "Oslo", "Nairobi")); for (int i = 0; i < cities.size(); i++) { System.out.println(cities.get(i)); }

When the collection is an ArrayList, get(i) runs in constant time, so index-based iteration is efficient. When the collection is a LinkedList, get(i) traverses the list from the head on every call, making this pattern O(n²) overall. The enhanced for loop avoids that problem because it uses the collection's iterator.

The Enhanced for Loop

Java's enhanced for loop, also called the for-each loop, iterates over arrays and any object that implements Iterable. It removes the need to manage an index or call get() explicitly.

List<String> cities = new ArrayList<>(List.of("Tokyo", "Oslo", "Nairobi")); for (String city : cities) { System.out.println(city); }

The enhanced loop compiles to an iterator-based traversal for collections and an index-based traversal for arrays. It is the preferred choice when you only need the current element and do not need its position. The main limitation is that you cannot modify the collection while iterating with this construct without risking a ConcurrentModificationException, and you have no access to the index.

Loop Performance and Runtime Behavior

The condition in a for loop header is evaluated on every iteration. If the condition performs work, that work is repeated. A common pattern is caching the size of a collection in a local variable when the collection is large and the size method is not cheap. For ArrayList, size() is a field read, so caching is unnecessary. For a LinkedList, calling size() repeatedly is also cheap because the field is stored, but the traversal cost of get(i) dominates.

The enhanced for loop on a LinkedList uses the iterator, which advances one node per step, giving O(n) total traversal. The index-based loop on the same list calls get(i) for each i, each call starting from the head, giving O(n²) total. This is the most significant performance difference between the two loop styles.

The JIT compiler can optimize tight loops, but it cannot remove the algorithmic cost of repeated get(i) calls on a linked structure.

Common Mistakes and Edge Cases

One off-by-one error: using i <= values.length causes an ArrayIndexOutOfBoundsException on the final iteration. The valid indices range from 0 through length - 1.

Another issue is modifying a collection during iteration. Removing an element while using the enhanced for loop throws ConcurrentModificationException because the iterator detects structural modification. Removing an element while using an index-based loop shifts subsequent elements, so you may skip the next element. The safe approach for removal is to iterate backwards or use an explicit Iterator and call remove().

List<Integer> numbers = new ArrayList<>(List.of(1, 2, 3, 4)); Iterator<Integer> it = numbers.iterator(); while (it.hasNext()) { if (it.next() % 2 == 0) { it.remove(); } }

Forgetting the update expression, such as writing for (int i = 0; i < 10;), creates an infinite loop unless the body changes i itself. The compiler does not warn about this.

When to Use Each Loop Form

The choice between the traditional for loop, the enhanced for loop, and the iterator-based loop depends on what the body needs.

Use the traditional index-based for loop when you need the index, when you must iterate in reverse, or when you need to access multiple collections at the same position. Use the enhanced for loop when you only need each element in forward order and the collection is not being modified. Use an explicit Iterator when you need to remove elements during traversal or when you need to advance more than one element per step.

The enhanced for loop is also the clearest choice for arrays when the index is irrelevant, because it eliminates the risk of off-by-one errors entirely.

java for loop: Practical Usage and Code Examples | RYUSLOG DEV