☕ Java

for Loop

The for loop is the most widely used iteration construct in Java. It combines initialisation, condition checking, and increment/decrement into a single compact header, making the loop's structure immediately visible. Java's for loop is a count-controlled loop — it is the natural choice whenever the number of iterations is known before the loop begins. This entry covers syntax, execution flow, nested loops, loop control statements, common patterns, and performance considerations.

Syntax and Execution Flow

The for loop header has three semicolon-separated parts enclosed in parentheses: the initialisation expression, the boolean condition, and the update expression. The initialisation runs once before the loop begins. Before each iteration — including the first — the condition is evaluated; if it is false the loop exits immediately without executing the body. After each iteration the update expression runs, then the condition is re-evaluated. This means a for loop whose condition is false from the start executes its body zero times, which is the correct and expected behaviour. The scope of a variable declared in the initialisation section is limited to the loop header and body. Declaring the loop variable inside the header (int i = 0) rather than outside is idiomatic Java and prevents accidental reuse of the variable after the loop.
Java
// ── Anatomy of a for loop ────────────────────────────────────────────
//
//   for ( initialisation ; condition ; update ) {
//         body
//   }
//
//   Execution order:
//   1. initialisation  — runs ONCE before everything
//   2. condition       — evaluated BEFORE each iteration (including first)
//   3. body            — runs if condition is true
//   4. update          — runs AFTER each body execution
//   5. back to step 2

for (int i = 0; i < 5; i++) {
    System.out.println("Iteration: " + i);
}
// Output: 0  1  2  3  4

// ── Condition false from the start — body never runs ─────────────────
for (int i = 10; i < 5; i++) {
    System.out.println("This never prints");
}
// No output — condition (10 < 5) is immediately false

// ── Variable scope — i only exists inside the loop ───────────────────
for (int i = 0; i < 3; i++) {
    System.out.println(i);
}
// System.out.println(i); // ← compile error — i is out of scope

// ── Multiple variables in initialisation and update ───────────────────
for (int i = 0, j = 10; i < j; i++, j--) {
    System.out.println("i=" + i + " j=" + j);
}
// Output: i=0 j=10 | i=1 j=9 | i=2 j=8 | i=3 j=7 | i=4 j=6

// ── Counting down ─────────────────────────────────────────────────────
for (int i = 5; i > 0; i--) {
    System.out.println("Countdown: " + i);
}
// Output: 5  4  3  2  1

// ── Step other than 1 ─────────────────────────────────────────────────
for (int i = 0; i <= 20; i += 5) {
    System.out.println(i);   // 0  5  10  15  20
}

// ── Infinite loop (all three parts are optional) ──────────────────────
for (;;) {
    // Equivalent to while (true)
    // Requires a break or return to exit
    if (someCondition) break;
}

Iterating Over Arrays and Lists

The indexed for loop is the right choice when you need the index value during iteration — to compare adjacent elements, to update elements in place, to iterate over two collections simultaneously, or to iterate in reverse. For read-only forward iteration over a collection, the enhanced for loop is cleaner; the indexed form is superior when the position matters. Accessing arrays by index is a constant-time O(1) operation — the JVM computes the memory address directly from the base address and index. For ArrayList, random access is also O(1). For LinkedList, random access by index is O(n) — use an iterator or enhanced for loop instead.
Java
// ── Iterating an array by index ──────────────────────────────────────
int[] scores = {85, 92, 78, 96, 88};

int sum = 0;
for (int i = 0; i < scores.length; i++) {
    sum += scores[i];
}
double average = (double) sum / scores.length;
System.out.println("Average: " + average);   // 87.8

// ── Modifying array elements in place ─────────────────────────────────
// Enhanced for loop gives a COPY — cannot modify original
// Index loop modifies the array directly
for (int i = 0; i < scores.length; i++) {
    scores[i] = scores[i] + 5;   // add 5 bonus points
}

// ── Comparing adjacent elements ───────────────────────────────────────
int[] numbers = {3, 1, 4, 1, 5, 9, 2, 6};
for (int i = 0; i < numbers.length - 1; i++) {
    if (numbers[i] > numbers[i + 1]) {
        System.out.println(numbers[i] + " > " + numbers[i + 1]);
    }
}

// ── Iterating a List with index ───────────────────────────────────────
List<String> names = List.of("Alice", "Bob", "Carol", "Dave");
for (int i = 0; i < names.size(); i++) {
    System.out.printf("[%d] %s%n", i, names.get(i));
}
// Output: [0] Alice  [1] Bob  [2] Carol  [3] Dave

// ── Iterating in reverse ──────────────────────────────────────────────
for (int i = names.size() - 1; i >= 0; i--) {
    System.out.println(names.get(i));
}
// Output: Dave  Carol  Bob  Alice

// ── Parallel iteration over two arrays ───────────────────────────────
String[] keys   = {"name",    "email",              "role"};
String[] values = {"Alice",   "alice@example.com",  "ADMIN"};

for (int i = 0; i < keys.length; i++) {
    System.out.println(keys[i] + " = " + values[i]);
}

Nested for Loops

A nested for loop places one loop inside the body of another. The inner loop completes all its iterations for every single iteration of the outer loop. If the outer loop runs m times and the inner loop runs n times, the body of the inner loop executes m × n times total. This O(m×n) growth means nested loops should be used with care for large inputs. The outer loop variable controls the row (or first dimension) and the inner loop variable controls the column (or second dimension). Each variable must have a distinct name. Deeply nested loops — three or more levels — are usually a signal that the code should be refactored into methods.
Java
// ── Multiplication table ─────────────────────────────────────────────
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= 5; j++) {
        System.out.printf("%4d", i * j);
    }
    System.out.println();
}
// Output:
//    1   2   3   4   5
//    2   4   6   8  10
//    3   6   9  12  15
//    4   8  12  16  20
//    5  10  15  20  25

// ── 2D array processing ───────────────────────────────────────────────
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

int total = 0;
for (int row = 0; row < matrix.length; row++) {
    for (int col = 0; col < matrix[row].length; col++) {
        total += matrix[row][col];
        System.out.printf("%3d", matrix[row][col]);
    }
    System.out.println();
}
System.out.println("Sum: " + total);   // 45

// ── Star pattern — outer controls rows, inner controls columns ────────
for (int row = 1; row <= 5; row++) {
    for (int star = 1; star <= row; star++) {
        System.out.print("* ");
    }
    System.out.println();
}
// Output:
// *
// * *
// * * *
// * * * *
// * * * * *

// ── Bubble sort — classic nested loop algorithm ───────────────────────
int[] arr = {64, 34, 25, 12, 22, 11, 90};
int n = arr.length;

for (int i = 0; i < n - 1; i++) {
    for (int j = 0; j < n - i - 1; j++) {
        if (arr[j] > arr[j + 1]) {
            // Swap
            int temp = arr[j];
            arr[j]   = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}
System.out.println(Arrays.toString(arr));
// Output: [11, 12, 22, 25, 34, 64, 90]

break, continue, and Labelled Statements

break exits the innermost enclosing loop immediately, skipping any remaining iterations. continue skips the rest of the current iteration's body and jumps to the update expression, then re-evaluates the condition. Both are useful for expressing early-exit and skip-and-continue logic cleanly. Java supports labelled break and labelled continue for nested loops. A label is an identifier followed by a colon placed before a loop statement. labelled break exits the labelled loop entirely; labelled continue skips to the update of the labelled loop. Labels should be used sparingly — they can make control flow harder to follow — but they are the cleanest way to exit a nested loop without an extra boolean flag variable.
Java
// ── break — exit the loop immediately ───────────────────────────────
int[] numbers = {3, 7, 2, 9, 4, 6, 1};
int target = 9;
int foundAt = -1;

for (int i = 0; i < numbers.length; i++) {
    if (numbers[i] == target) {
        foundAt = i;
        break;          // stop searching once found
    }
}
System.out.println("Found at index: " + foundAt);   // 3

// ── continue — skip this iteration, go to next ───────────────────────
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;   // skip even numbers
    System.out.print(i + " ");  // prints: 1 3 5 7 9
}

// ── Labelled break — exit an outer loop ──────────────────────────────
// Without label: must use a boolean flag (verbose)
boolean found = false;
int foundRow = -1, foundCol = -1;
outer:
for (int row = 0; row < matrix.length; row++) {
    for (int col = 0; col < matrix[row].length; col++) {
        if (matrix[row][col] == 5) {
            foundRow = row;
            foundCol = col;
            break outer;   // exits BOTH loops
        }
    }
}
System.out.println("Found at [" + foundRow + "][" + foundCol + "]");

// ── Labelled continue — skip to the next outer iteration ─────────────
outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 1) continue outer;   // skip rest of inner loop
        System.out.println("i=" + i + " j=" + j);
    }
}
// Output: i=0 j=0 | i=1 j=0 | i=2 j=0
// (j=1 and j=2 are never reached because continue outer
//  jumps to the next outer iteration before they execute)

Common Patterns and Idioms

The indexed for loop appears in many canonical algorithms and patterns. Understanding these idioms — finding min/max, accumulating a result, building a string, partitioning a range — builds the muscle memory to reach for the right tool quickly. Each pattern below represents a general template that can be adapted to the specific problem at hand.
Java
// ── Pattern 1: Accumulator ────────────────────────────────────────────
// Sum, product, count, concatenation — same structure
int[] prices = {10, 25, 8, 42, 15};

int    sum     = 0;
double product = 1.0;
int    count   = 0;

for (int i = 0; i < prices.length; i++) {
    sum     += prices[i];
    product *= prices[i];
    if (prices[i] > 15) count++;
}

// ── Pattern 2: Find min/max ───────────────────────────────────────────
int min = prices[0];
int max = prices[0];
int minIndex = 0;
int maxIndex = 0;

for (int i = 1; i < prices.length; i++) {  // start at 1 — skip first
    if (prices[i] < min) { min = prices[i]; minIndex = i; }
    if (prices[i] > max) { max = prices[i]; maxIndex = i; }
}
System.out.println("Min: " + min + " at " + minIndex);
System.out.println("Max: " + max + " at " + maxIndex);

// ── Pattern 3: Building a result string ───────────────────────────────
String[] fruits = {"apple", "banana", "cherry"};
StringBuilder sb = new StringBuilder();

for (int i = 0; i < fruits.length; i++) {
    sb.append(fruits[i]);
    if (i < fruits.length - 1) sb.append(", ");
}
System.out.println(sb.toString());   // apple, banana, cherry

// ── Pattern 4: Two-pointer technique ─────────────────────────────────
// Check if a string is a palindrome
String word = "racecar";
char[] chars = word.toCharArray();
boolean isPalindrome = true;

for (int left = 0, right = chars.length - 1;
         left < right;
         left++, right--) {
    if (chars[left] != chars[right]) {
        isPalindrome = false;
        break;
    }
}
System.out.println(word + " is palindrome: " + isPalindrome);

// ── Pattern 5: Collect matching elements ──────────────────────────────
int[] data = {3, 8, 2, 15, 7, 22, 4, 18, 11};
List<Integer> evens = new ArrayList<>();

for (int i = 0; i < data.length; i++) {
    if (data[i] % 2 == 0) {
        evens.add(data[i]);
    }
}
System.out.println("Even numbers: " + evens);   // [8, 2, 22, 4, 18]

Related Topics in Control Statements

while Loop
The while loop is a condition-controlled loop — it continues executing as long as its boolean condition remains true, without specifying in advance how many iterations will occur. It is the natural choice for reading input until end-of-stream, polling until a condition changes, retrying an operation, or any scenario where the termination condition depends on data or events that cannot be predetermined. This entry covers syntax, execution flow, common patterns, infinite loops with controlled exit, and the differences between while and for.
do-while Loop
The do-while loop is Java's only post-test loop — the condition is evaluated after the body executes, which guarantees the body runs at least once regardless of the condition's initial value. This property makes do-while the natural fit for scenarios where the first execution must happen before the first check: menu-driven programs, input validation, digest computation, and game turns. This entry covers syntax, when to use do-while over while, input validation patterns, and the subtle differences that matter in practice.
Enhanced for Loop
The enhanced for loop — also called the for-each loop — was introduced in Java 5 to provide a clean, readable syntax for iterating over arrays and any class that implements Iterable. It eliminates index management and iterator boilerplate entirely. The developer declares what each element is and what to do with it, without concerning themselves with how the iteration mechanism works. This entry covers syntax, the Iterable contract, limitations compared to the indexed loop, modification restrictions, and how for-each maps to iterators under the hood.
break Statement
The break statement immediately terminates the nearest enclosing loop or switch block and transfers control to the first statement after that block. It is one of Java's three jump statements alongside continue and return. break is essential for exiting loops early when a search condition is met, preventing infinite loops from running forever, and stopping switch execution after a matched case.