Skip to lesson
CodeLangs AISoftware Training Institute
Loops and Iteration

Chapter 7 · Java Control Flow

Loops and Iteration

Master loops and iteration in Java, including for, while, do-while, the enhanced for loop, break, continue, labeled break and continue, nested loops, common loop patterns, array and collection iteration, and the mistakes developers commonly make while working with repetition.

  • 6,515words
  • 30min read
  • 12quiz items
  • 16practice tools

A program normally executes one statement, then the next statement, then the next.

That works until a requirement says something like:

  • Print numbers from 1 to 100.
  • Process every employee in an array.
  • Keep asking for input until the user enters a valid value.
  • Search for a product until it is found.
  • Repeat an operation for every row and column.
  • Skip invalid records but continue processing valid ones.
  • Stop processing as soon as a required value is found.

You could write the same statement repeatedly:

Java
System.out.println(1);
System.out.println(2);
System.out.println(3);
System.out.println(4);
System.out.println(5);

But imagine doing this for 10,000 values.

That would be repetitive, difficult to maintain, and completely impractical.

So programming languages provide a way to say:

"Execute this block repeatedly according to a rule."

That mechanism is called a loop.

This chapter covers Java loops, loop-control statements, loop patterns, array and collection iteration, and the mistakes developers commonly make while working with iteration.


1. Why Loops Are Required#

Before learning loop syntax, understand the problem loops solve.

Suppose we want to print numbers from 1 through 5.

Without a loop:

Java
public class Main {
    public static void main(String[] args) {
        System.out.println(1);
        System.out.println(2);
        System.out.println(3);
        System.out.println(4);
        System.out.println(5);
    }
}

This technically works.

But now the requirement changes:

Print numbers from 1 through 1,000,000.

Writing one million println() statements is clearly not reasonable.

What actually changes between those statements?

Only the value:

Output
1
2
3
4
5
...

The operation stays the same:

Java
System.out.println(...)

So what we really want is:

Output
Start with 1
↓
Print it
↓
Increase it
↓
Still within the limit?
    ↓ Yes
Repeat
    ↓ No
Stop

That is the basic idea behind iteration.

What is iteration?#

Iteration means performing one repetition of a loop.

Consider:

Java
for (int i = 1; i <= 3; i++) {
    System.out.println(i);
}

The loop body executes three times.

Therefore:

  • first execution = first iteration
  • second execution = second iteration
  • third execution = third iteration

Output:

Output
1
2
3

What does a loop normally need?#

Most loops involve three ideas:

Output
Starting State
     ↓
Condition
     ↓
Execute Work
     ↓
Change State
     ↓
Check Condition Again

For example:

Output
i = 1
↓
Is i <= 5?
↓
Print i
↓
i++
↓
Check again

The variable controlling this repetition is often called a loop control variable.


2. Before Learning Individual Loops: The Core Mental Model#

Different Java loops look different syntactically, but internally they revolve around one question:

Should the loop execute another iteration?

Consider:

Java
int i = 1;

while (i <= 3) {
    System.out.println(i);
    i++;
}

Execution:

Output
i = 1
  ↓
i <= 3 ? → true
  ↓
print 1
  ↓
i becomes 2
  ↓
i <= 3 ? → true
  ↓
print 2
  ↓
i becomes 3
  ↓
i <= 3 ? → true
  ↓
print 3
  ↓
i becomes 4
  ↓
i <= 3 ? → false
  ↓
Loop terminates

Output:

Output
1
2
3

There are several ways Java expresses this repetition:

LoopBest mental model
forRepeat with an explicit counter/progression
whileRepeat while a condition remains true
do-whileExecute once, then decide whether to repeat
enhanced forProcess each element of an array or Iterable

We will now understand why each one exists instead of merely memorizing syntax.


3. The for Loop#

Suppose we know in advance that something should happen five times.

We need:

  1. a starting value
  2. a condition
  3. an update after every iteration

We could write all of these separately with while, but because this pattern is extremely common, Java gives us a compact structure that keeps these three pieces together.

for Loop Syntax#

Java
for (initialization; condition; update) {
    // statements
}

Example:

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

Output:

Output
1
2
3
4
5

Let's understand the three important parts.

Java
int i = 1

This is the initialization.

It establishes the starting state.

Java
i <= 5

This is the condition.

The loop continues while this expression evaluates to true.

Java
i++

This is the update expression.

It executes after each normal iteration.


Exact Execution Order#

One of the most important interview and debugging concepts is the execution order.

For:

Java
for (int i = 1; i <= 3; i++) {
    System.out.println(i);
}

Java conceptually performs:

Output
1. int i = 1
        ↓
2. Check i <= 3
        ↓ true
3. Execute loop body
        ↓
4. Execute i++
        ↓
5. Check i <= 3 again
        ↓
6. Repeat

Initialization happens only once.

Condition may execute multiple times.

Update normally executes after every completed iteration.

Detailed trace#

Output
Initialization:
i = 1

Condition:
1 <= 3 → true

Body:
print 1

Update:
i = 2

Condition:
2 <= 3 → true

Body:
print 2

Update:
i = 3

Condition:
3 <= 3 → true

Body:
print 3

Update:
i = 4

Condition:
4 <= 3 → false

STOP

Notice something important:

The condition was checked four times, even though the body executed only three times.

The final condition check is what determines that execution should stop.


4. Understanding i++#

A new expression appeared:

Java
i++;

Before continuing, understand it.

i++ increments i by 1.

For this standalone usage:

Java
i++;

it effectively means:

Java
i = i + 1;

Example:

Java
int i = 5;
i++;
System.out.println(i);

Output:

Output
6

For loop control, you'll commonly see:

Java
i++

or:

Java
i--

i-- decreases the variable by 1.


5. Counting Backward#

Loops don't have to move forward.

Requirement:

Print 5 to 1.
Java
for (int i = 5; i >= 1; i--) {
    System.out.println(i);
}

Output:

Output
5
4
3
2
1

Mental model:

Output
Start 5
↓
Is value >= 1?
↓
Print
↓
Decrease by 1
↓
Repeat

6. Changing the Step Size#

The update expression does not have to change the variable by exactly 1.

Requirement:

Print even numbers from 2 through 10.
Java
for (int i = 2; i <= 10; i += 2) {
    System.out.println(i);
}

Output:

Output
2
4
6
8
10

Here:

Java
i += 2;

means:

Java
i = i + 2;

Another example:

Java
for (int i = 10; i >= 0; i -= 2) {
    System.out.println(i);
}

Output:

Output
10
8
6
4
2
0

7. More Than One Variable in a for Loop#

A for statement may initialize and update multiple compatible variables.

Java
for (int left = 0, right = 10; left < right; left++, right--) {
    System.out.println(left + " " + right);
}

Possible output:

Output
0 10
1 9
2 8
3 7
4 6

Important distinction:

Java does not generally have a C-style comma operator.

But the initialization and update portions of a for statement allow comma-separated expressions/declarators according to Java's for syntax.


8. Scope of a for Loop Variable#

Consider:

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

The variable i declared inside the for initialization belongs to the scope of that loop.

This will not compile:

Java
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            System.out.println(i);
        }

        System.out.println(i);
    }
}

i is no longer available outside the loop.

If you genuinely need it afterward:

Java
int i;

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

System.out.println("Final i = " + i);

Output:

Output
0
1
2
Final i = 3

Prefer the smallest reasonable variable scope. Don't move loop variables outside merely because you can.


9. Missing Parts in a for Loop#

Java allows all three major for components to be omitted.

Example:

Java
int i = 1;

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

Initialization occurred before the loop.

This is valid.

You could even write:

Java
int i = 1;

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

Still valid.

And:

Java
for (;;) {
    System.out.println("Running");
}

is also valid.

But this last example has no termination condition.

It is an infinite loop, which we will discuss later.


10. When Should You Choose for?#

A practical rule:

Output
Do I have an obvious counter, range, or progression?
              ↓
             Yes
              ↓
           Use for

Examples:

  • 1 through 100
  • array indexes
  • fixed retry attempts
  • countdowns
  • stepping through positions
  • repeating something n times

11. The while Loop#

Now consider another problem.

Suppose you don't know exactly how many attempts will be required.

For example:

Keep processing while the system has pending work.

You may not know whether there will be:

  • 1 iteration
  • 5 iterations
  • 500 iterations
  • zero iterations

The key idea is not "repeat 10 times."

The key idea is:

Repeat while some condition remains true.

That is where while fits naturally.

Syntax#

Java
while (condition) {
    // statements
}

Example:

Java
int i = 1;

while (i <= 5) {
    System.out.println(i);
    i++;
}

Output:

Output
1
2
3
4
5

12. while Execution Flow#

Output
Condition
   ↓
 true? ── No ──→ Stop
   │
  Yes
   ↓
Execute body
   ↓
Return to condition

Notice the important point:

while checks its condition before entering the body.

This means the body may execute zero times.

Example:

Java
int number = 10;

while (number < 5) {
    System.out.println(number);
}

Output:

Output
No output

Because:

Output
10 < 5 → false

The body is never entered.


13. while and State Changes#

Consider:

Java
int i = 1;

while (i <= 3) {
    System.out.println(i);
}

Before reading further, predict what happens.

i starts as 1.

Condition:

Java
i <= 3

is true.

But does anything change i?

No.

Therefore Java keeps seeing:

Output
1 <= 3 → true

again and again.

The loop does not terminate naturally.

Correct version:

Java
int i = 1;

while (i <= 3) {
    System.out.println(i);
    i++;
}

One essential rule should now be clear:

If termination depends on changing state, make sure something inside the loop actually changes that state.

14. Practical while Example#

Imagine processing jobs while work remains.

Java
int pendingJobs = 3;

while (pendingJobs > 0) {
    System.out.println("Processing job...");
    pendingJobs--;
}

System.out.println("All jobs processed.");

Output:

Output
Processing job...
Processing job...
Processing job...
All jobs processed.

In production, pendingJobs might come from application state rather than a hardcoded integer, but the conceptual pattern is the same.


15. When Should You Choose while?#

Use while naturally when continuation is driven primarily by a condition rather than a clean counter.

Examples:

Output
While connection remains active
While input is invalid
While queue is not empty
While data is available
While operation has not completed
While balance remains positive

Decision rule:

Output
Known counter/range?
→ for

Condition-driven repetition?
→ while

16. The do-while Loop#

There is one limitation in while.

Its condition is tested before execution.

Therefore its body may execute zero times.

But some requirements say:

Perform the action first. Then decide whether it should happen again.

Consider a menu.

The program should display the menu at least once.

Only after that do we ask whether the user wants to continue.

For such cases Java provides do-while.

Syntax#

Java
do {
    // statements
} while (condition);

Notice the semicolon:

Java
while (condition);

It is required in the do-while syntax.

Example:

Java
int i = 1;

do {
    System.out.println(i);
    i++;
} while (i <= 5);

Output:

Output
1
2
3
4
5

17. Why do-while Is Different#

Consider:

Java
int number = 10;

do {
    System.out.println(number);
} while (number < 5);

Output:

Output
10

Why?

Execution order:

Output
Execute body first
      ↓
Print 10
      ↓
Check 10 < 5
      ↓
false
      ↓
Stop

Compare that with:

Java
int number = 10;

while (number < 5) {
    System.out.println(number);
}

Output:

Output
No output

This produces the fundamental difference:

whiledo-while
Condition checked firstBody executed first
Zero or more executionsOne or more executions
Entry-controlledExit-controlled
Good when work may not be neededGood when first execution is mandatory

18. Typical do-while Use Cases#

Historically common examples include:

  • console menus
  • retry prompts
  • input validation
  • repeating a user interaction
  • command-line applications

Example:

Java
int choice = 1;

do {
    System.out.println("Menu displayed");
    choice++;
} while (choice <= 3);

In production applications, the exact UI mechanism may be different, but the language behavior remains important.


19. Choosing Between for, while, and do-while#

Now we can build a useful decision model.

Output
Need repetition
     │
     ├── Known range/count/progression?
     │        └── for
     │
     ├── Condition determines whether execution begins?
     │        └── while
     │
     └── Must execute at least once?
              └── do-while

Comparison#

Dimensionforwhiledo-while
Initial condition checkYesYesNo
Minimum body executions001
Counter-friendlyExcellentPossiblePossible
Condition-driven workPossibleExcellentGood
Update locationUsually headerUsually bodyUsually body
Typical readabilityHigh for countingHigh for unknown iterationsHigh for execute-once-first requirements

These loops are not different in computational power for most ordinary tasks. Often one can be rewritten using another.

The correct choice is usually about expressing intent clearly.


20. Enhanced for Loop#

Suppose we have an array:

Java
int[] numbers = {10, 20, 30, 40};

A traditional indexed loop works:

Java
for (int i = 0; i < numbers.length; i++) {
    System.out.println(numbers[i]);
}

But imagine our requirement is simply:

Give me every value.

We don't actually care about i.

The index exists only because the traditional loop requires us to reach each array position.

Java therefore provides a shorter form for element-by-element traversal.

This is commonly called the:

  • enhanced for loop
  • for-each loop

Syntax#

Java
for (Type variable : arrayOrIterable) {
    // use variable
}

Example:

Java
int[] numbers = {10, 20, 30, 40};

for (int number : numbers) {
    System.out.println(number);
}

Output:

Output
10
20
30
40

Read it naturally as:

For each number in numbers, execute the body.

21. Enhanced for with Objects#

Java
String[] names = {"Amit", "Riya", "Neha"};

for (String name : names) {
    System.out.println(name);
}

Output:

Output
Amit
Riya
Neha

The variable:

Java
name

receives each array element, one at a time.


22. Important Limitation of Enhanced for#

Suppose you need the element's index:

Output
Position 0
Position 1
Position 2

The enhanced loop does not directly provide the index.

Use an indexed loop:

Java
String[] names = {"Amit", "Riya", "Neha"};

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

Output:

Output
0 -> Amit
1 -> Riya
2 -> Neha

Decision rule:

Output
Need only each element?
→ enhanced for

Need position/index?
→ traditional indexed for

23. Reassigning the Enhanced-Loop Variable#

This is an important trap.

Consider:

Java
int[] numbers = {1, 2, 3};

for (int number : numbers) {
    number = number * 10;
}

for (int number : numbers) {
    System.out.println(number);
}

What do you expect?

Output:

Output
1
2
3

Why didn't the array become:

Output
10
20
30

Because the enhanced-loop variable:

Java
number

contains the current primitive value.

Changing that local variable doesn't rewrite the array slot.

To modify array elements, use their indexes:

Java
int[] numbers = {1, 2, 3};

for (int i = 0; i < numbers.length; i++) {
    numbers[i] = numbers[i] * 10;
}

Now the array contains:

Output
10
20
30

For object references, the nuance is different: reassigning the local reference does not replace the collection/array element, but mutating the referenced object's state can affect the same object.


24. Internal Model of Enhanced for#

This is useful for interviews.

For arrays:

Java
for (int number : numbers) {
    System.out.println(number);
}

Java handles array traversal using array positions internally according to the language's enhanced-for translation model.

Conceptually:

Output
Array
 ↓
Element 0
 ↓
Element 1
 ↓
Element 2
 ↓
...

For an Iterable, such as most collection types:

Java
for (String name : names) {
    System.out.println(name);
}

the enhanced-for mechanism is based on an Iterator.

Conceptual model:

Output
Iterable
   ↓
iterator()
   ↓
hasNext()
   ↓
next()
   ↓
Loop body
   ↓
hasNext()
   ↓
...

We'll return to Iterator when we discuss collection iteration.


25. Nested Loops#

So far every loop has contained ordinary statements.

But Java allows a loop inside another loop.

Before introducing the name, imagine this requirement:

For every row, process every column.

If there are:

Output
3 rows
4 columns per row

then processing looks like:

Output
Row 1 → Column 1, 2, 3, 4
Row 2 → Column 1, 2, 3, 4
Row 3 → Column 1, 2, 3, 4

That naturally requires one repetition to exist inside another.

This is called loop nesting.

Example#

Java
for (int row = 1; row <= 3; row++) {
    for (int column = 1; column <= 4; column++) {
        System.out.println("Row " + row + ", Column " + column);
    }
}

The outer loop controls rows.

The inner loop controls columns.


26. Nested Loop Execution#

For:

Java
for (int i = 1; i <= 2; i++) {
    for (int j = 1; j <= 3; j++) {
        System.out.println(i + " " + j);
    }
}

Output:

Output
1 1
1 2
1 3
2 1
2 2
2 3

Execution:

Output
Outer i = 1
    ↓
    Inner j = 1
    Inner j = 2
    Inner j = 3
    ↓
Outer i = 2
    ↓
    Inner j = 1
    Inner j = 2
    Inner j = 3

The inner loop finishes all of its iterations for each outer-loop iteration.


27. Multiplication Table with Nested Loops#

Java
for (int row = 1; row <= 3; row++) {
    for (int column = 1; column <= 3; column++) {
        System.out.print((row * column) + "\t");
    }

    System.out.println();
}

Output:

Output
1	2	3
2	4	6
3	6	9

28. Time Complexity Intuition#

A new concept matters here.

Suppose the outer loop executes n times.

For each outer iteration, the inner loop also executes n times.

Approximately:

Output
n × n = n²

operations occur.

This is commonly described as:

Output
O(n²)

You don't need a complete algorithm-analysis course here. The important idea is:

Nested loops can multiply the amount of work.

But don't automatically assume every nested loop is O(n²).

Example:

Java
for (int i = 0; i < n; i++) {
    for (int j = 0; j < 5; j++) {
        // work
    }
}

The inner loop always runs only five times.

Work grows approximately as:

Output
5n

which is linear with respect to n.

So analyze actual iteration counts instead of counting braces.


29. Infinite Loops#

Most loops are expected to terminate.

But what happens if their continuation condition never becomes false?

The loop keeps executing.

That is an infinite loop.

Example:

Java
while (true) {
    System.out.println("Running");
}

This does not naturally terminate.

Another form:

Java
for (;;) {
    System.out.println("Running");
}

Also infinite.

And this accidental form:

Java
int i = 1;

while (i <= 5) {
    System.out.println(i);
}

is also effectively infinite because i never changes.


30. Are Infinite Loops Always Wrong?#

No.

This distinction matters.

An infinite loop can be:

  • intentional
  • accidental

Intentional loops are used in systems such as:

  • long-running worker processes
  • event-processing loops
  • servers
  • message consumers
  • game loops
  • embedded systems

A simplified worker pattern:

Java
while (true) {
    // wait for and process work
}

Production implementations need proper lifecycle control, interruption, error handling, shutdown behavior, and resource management. A naked while (true) is not automatically a complete production design.

The problem isn't "infinite loop = wrong."

The problem is:

Does the loop have a valid lifecycle and a controlled termination strategy when termination is required?

31. break#

Imagine searching an array.

Java
int[] numbers = {10, 20, 30, 40, 50};

We want to find 30.

Once 30 has been found, should we continue inspecting 40 and 50?

No.

The useful work is finished.

Java therefore gives us a statement that exits the nearest applicable loop immediately.

That statement is break.

Example#

Java
int[] numbers = {10, 20, 30, 40, 50};

for (int number : numbers) {
    if (number == 30) {
        System.out.println("Found");
        break;
    }

    System.out.println("Checked " + number);
}

Output:

Output
Checked 10
Checked 20
Found

Values after 30 are not processed.


32. break Execution Model#

Output
Loop iteration
     ↓
Condition for break?
     │
    No
     ↓
Continue body
     ↓
Next iteration

If Yes:
     ↓
break
     ↓
Exit loop immediately
     ↓
Continue after loop

Example:

Java
for (int i = 1; i <= 10; i++) {
    if (i == 4) {
        break;
    }

    System.out.println(i);
}

System.out.println("Finished");

Output:

Output
1
2
3
Finished

When i == 4, break executes before println(i).


33. break in while#

break isn't limited to for.

Java
int i = 1;

while (true) {
    if (i > 3) {
        break;
    }

    System.out.println(i);
    i++;
}

Output:

Output
1
2
3

Here the loop condition itself is always true, but a controlled break terminates execution.

This can be legitimate when the exit rule is clearer inside the body.


34. continue#

Now consider a different requirement.

Suppose we want to process numbers 1 through 5, except number 3.

When we reach 3, we don't want to terminate the entire loop.

We only want to skip the current iteration.

That requires different behavior.

continue does exactly that.

Example#

Java
for (int i = 1; i <= 5; i++) {
    if (i == 3) {
        continue;
    }

    System.out.println(i);
}

Output:

Output
1
2
4
5

The loop did not terminate.

Only the remainder of the i == 3 iteration was skipped.


35. break vs continue#

This distinction must be crystal clear.

Output
break
→ exit the loop

continue
→ skip the rest of the current iteration
→ attempt the next iteration

Comparison:

Dimensionbreakcontinue
Terminates loopYesNo
Skips current remainderYesYes
Future iterations occurNoNormally yes
Typical useSearch completedIgnore one item
ExampleStop after match foundSkip invalid record

36. A Common continue Bug in while#

Look carefully:

Java
int i = 0;

while (i < 5) {
    if (i == 2) {
        continue;
    }

    System.out.println(i);
    i++;
}

What happens?

Trace:

Output
i = 0 → print → i = 1
i = 1 → print → i = 2
i = 2 → continue
i still = 2
i = 2 → continue
i still = 2
...

Infinite loop.

The update was placed after the possible continue.

One correction:

Java
int i = 0;

while (i < 5) {
    if (i == 2) {
        i++;
        continue;
    }

    System.out.println(i);
    i++;
}

A cleaner structure may avoid the duplicated increment:

Java
int i = 0;

while (i < 5) {
    if (i != 2) {
        System.out.println(i);
    }

    i++;
}

This demonstrates why control-flow statements must be considered together with loop-state updates.


37. Labeled break#

Nested loops introduce another problem.

Consider:

Java
for (int row = 0; row < 3; row++) {
    for (int column = 0; column < 3; column++) {
        if (row == 1 && column == 1) {
            break;
        }

        System.out.println(row + "," + column);
    }
}

The break exits only the nearest enclosing loop.

It exits the inner loop, but the outer loop continues.

Sometimes we need:

Exit a particular outer structure immediately.

Java provides labels.

Syntax#

Java
labelName:
for (...) {
    ...
}

Then:

Java
break labelName;

Example:

Java
outer:
for (int row = 0; row < 3; row++) {
    for (int column = 0; column < 3; column++) {
        if (row == 1 && column == 1) {
            break outer;
        }

        System.out.println(row + "," + column);
    }
}

System.out.println("Finished");

Output:

Output
0,0
0,1
0,2
1,0
Finished

break outer; exits the statement marked with outer.

In loop-oriented code, labels are usually encountered for nested-loop control.


38. Labeled continue#

Sometimes we don't want to terminate the outer loop.

Instead, we want to stop the current inner work and move to the next iteration of an outer loop.

That is where labeled continue can help.

Java
outer:
for (int row = 1; row <= 3; row++) {
    for (int column = 1; column <= 3; column++) {
        if (column == 2) {
            continue outer;
        }

        System.out.println(row + "," + column);
    }
}

Output:

Output
1,1
2,1
3,1

When:

Java
column == 2

Java performs:

Java
continue outer;

So the remainder of the current outer-loop iteration is abandoned and the next outer iteration begins.


39. Important Label Rule#

break label; and continue label; are related but not identical.

A labeled break can exit its labeled statement.

A labeled continue must target an appropriate enclosing loop/iteration statement because "continue" means move to another iteration.

This is valid:

Java
outer:
for (int i = 0; i < 5; i++) {
    continue outer;
}

Labels are useful, but heavy use can make control flow harder to understand.

In many production designs, extracting nested logic into well-named methods can improve readability.

So don't conclude:

"Labels are bad."

Instead:

Use them when they express nested-loop control more clearly than the available alternatives.

40. Loop Control Variables#

We've repeatedly used variables such as:

Java
i
j
row
column
attempt

These often determine:

  • current position
  • number of completed iterations
  • whether a boundary has been reached
  • how execution progresses

Good loop-control variable properties#

A loop-control variable should usually have:

  1. an understandable initial value
  2. a clear condition
  3. a predictable update
  4. a reachable termination state

Example:

Java
for (int attempt = 1; attempt <= 3; attempt++) {
    System.out.println("Attempt " + attempt);
}

This is easy to reason about.


41. Meaningful Names vs i#

Is i bad?

No.

For a tiny local index loop:

Java
for (int i = 0; i < numbers.length; i++) {
    System.out.println(numbers[i]);
}

i is conventional and easy to understand.

But deeply nested logic benefits from better names:

Less readable:

Java
for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.println(matrix[i][j]);
    }
}

Still acceptable because i and j are common matrix indexes.

For domain logic, however:

Java
for (int employeeIndex = 0; employeeIndex < employees.length; employeeIndex++) {
    // ...
}

may communicate intent better.

Choose names based on complexity and scope.


42. Off-by-One Errors#

One of the most common loop mistakes involves boundaries.

Suppose an array has five elements:

Java
int[] numbers = {10, 20, 30, 40, 50};

Indexes are:

Output
0
1
2
3
4

Not:

Output
1
2
3
4
5

The correct loop:

Java
for (int i = 0; i < numbers.length; i++) {
    System.out.println(numbers[i]);
}

A dangerous version:

Java
for (int i = 0; i <= numbers.length; i++) {
    System.out.println(numbers[i]);
}

Why?

When:

Java
i == numbers.length

the code tries to access index 5.

But valid indexes end at 4.

Result:

Output
ArrayIndexOutOfBoundsException

The classic array pattern is:

Java
i < array.length

not:

Java
i <= array.length

43. Loop Patterns#

Once syntax becomes comfortable, most real loop problems start looking like recurring patterns.

Recognizing these patterns is more valuable than memorizing dozens of isolated examples.


Pattern 1 — Counter#

Requirement:

Count how many values match a rule.
Java
int[] numbers = {3, 8, 10, 5, 12};
int evenCount = 0;

for (int number : numbers) {
    if (number % 2 == 0) {
        evenCount++;
    }
}

System.out.println(evenCount);

Output:

Output
3

Mental model:

Output
Start count at 0
↓
Inspect each item
↓
Match?
→ count++

44. Pattern 2 — Accumulator#

Requirement:

Calculate the total.
Java
int[] prices = {100, 200, 300};
int total = 0;

for (int price : prices) {
    total += price;
}

System.out.println(total);

Output:

Output
600

total is an accumulator.

It carries the partial result from one iteration to the next.


Requirement:

Determine whether a value exists.
Java
int[] numbers = {10, 20, 30, 40};
int target = 30;
boolean found = false;

for (int number : numbers) {
    if (number == target) {
        found = true;
        break;
    }
}

System.out.println(found);

Output:

Output
true

Why use break?

Once the target is found, further searching is unnecessary.


46. Pattern 4 — Find First Match#

Java
int[] numbers = {5, 12, 7, 20};
int firstEven = -1;

for (int number : numbers) {
    if (number % 2 == 0) {
        firstEven = number;
        break;
    }
}

System.out.println(firstEven);

Output:

Output
12

The sentinel value -1 means "not found" in this particular domain.

But be careful:

If -1 can be a valid data value, it becomes ambiguous.

In richer domain code, another representation may be better.


47. Pattern 5 — Minimum#

Java
int[] numbers = {8, 3, 12, 2, 9};

int minimum = numbers[0];

for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] < minimum) {
        minimum = numbers[i];
    }
}

System.out.println(minimum);

Output:

Output
2

Why start from:

Java
numbers[0]

instead of 0?

Suppose:

Java
{-8, -3, -15}

If minimum started as 0, it could still work for this negative example, but using an actual element creates a general data-derived baseline.

However, there is an important edge case:

Java
numbers[0]

is invalid for an empty array.

So production code must define how empty input should be handled.


48. Pattern 6 — Maximum#

Java
int[] numbers = {8, 3, 12, 2, 9};

int maximum = numbers[0];

for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] > maximum) {
        maximum = numbers[i];
    }
}

System.out.println(maximum);

Output:

Output
12

49. Pattern 7 — Filter/Skip#

Requirement:

Process only positive values.
Java
int[] numbers = {5, -3, 8, -1, 10};

for (int number : numbers) {
    if (number < 0) {
        continue;
    }

    System.out.println(number);
}

Output:

Output
5
8
10

An alternative:

Java
for (int number : numbers) {
    if (number >= 0) {
        System.out.println(number);
    }
}

Neither is universally better.

If skipping invalid items early reduces deep nesting, continue can improve readability.


50. Pattern 8 — Flag-Controlled Loop#

Java
boolean running = true;
int count = 0;

while (running) {
    count++;

    if (count == 3) {
        running = false;
    }
}

System.out.println(count);

Output:

Output
3

This pattern is useful when the loop's lifecycle is controlled by state.


51. Pattern 9 — Sentinel-Controlled Loop#

A sentinel is a special value indicating that processing should stop.

Conceptually:

Output
Read value
↓
Is value sentinel?
→ Yes: stop
→ No: process and continue

Simplified example:

Java
int[] input = {10, 20, 30, -1, 40};

for (int value : input) {
    if (value == -1) {
        break;
    }

    System.out.println(value);
}

Output:

Output
10
20
30

Here -1 acts as the sentinel.


52. Pattern 10 — Bounded Retry#

Real applications should often avoid uncontrolled retries.

Example:

Java
boolean success = false;

for (int attempt = 1; attempt <= 3 && !success; attempt++) {
    System.out.println("Attempt " + attempt);

    if (attempt == 2) {
        success = true;
    }
}

Output:

Output
Attempt 1
Attempt 2

Production retries are more complicated: delays, backoff, idempotency, transient failures, logging, metrics, and failure classification may matter.

But the fundamental bounded-loop pattern is worth understanding.


53. Pattern 11 — Reverse Traversal#

Java
int[] numbers = {10, 20, 30, 40};

for (int i = numbers.length - 1; i >= 0; i--) {
    System.out.println(numbers[i]);
}

Output:

Output
40
30
20
10

Initial index:

Java
numbers.length - 1

because the final valid array position is always one less than the length.


54. Pattern 12 — Two Ends Moving Toward Each Other#

Suppose we want to compare values from both ends.

Java
int[] numbers = {1, 2, 3, 2, 1};

boolean same = true;

for (int left = 0, right = numbers.length - 1;
     left < right;
     left++, right--) {

    if (numbers[left] != numbers[right]) {
        same = false;
        break;
    }
}

System.out.println(same);

Output:

Output
true

This demonstrates how one loop can maintain multiple control variables.


55. Iterating Arrays#

Arrays are one of the most common places beginners first use loops.

Suppose:

Java
int[] scores = {80, 90, 75, 95};

There are two common traversal approaches.

Indexed loop#

Java
for (int i = 0; i < scores.length; i++) {
    System.out.println(scores[i]);
}

Enhanced loop#

Java
for (int score : scores) {
    System.out.println(score);
}

Which one should you choose?

Output
Need element only?
→ enhanced for

Need index?
→ indexed for

Need to replace array positions?
→ indexed for

Need custom stepping/reverse traversal?
→ indexed for

56. Updating an Array#

Requirement:

Increase every score by 5.

Use indexes because array positions must be replaced.

Java
int[] scores = {80, 90, 75};

for (int i = 0; i < scores.length; i++) {
    scores[i] += 5;
}

for (int score : scores) {
    System.out.println(score);
}

Output:

Output
85
95
80

57. Two-Dimensional Arrays#

A two-dimensional array naturally introduces nested loops.

Java
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6}
};

Indexed traversal:

Java
for (int row = 0; row < matrix.length; row++) {
    for (int column = 0; column < matrix[row].length; column++) {
        System.out.print(matrix[row][column] + " ");
    }

    System.out.println();
}

Output:

Output
1 2 3
4 5 6

Notice:

Java
matrix[row].length

rather than assuming every row has the same size.

Java supports arrays whose rows have different lengths.

Example:

Java
int[][] data = {
    {1, 2},
    {3, 4, 5},
    {6}
};

This is sometimes called a jagged or ragged array.

Correct traversal:

Java
for (int row = 0; row < data.length; row++) {
    for (int column = 0; column < data[row].length; column++) {
        System.out.print(data[row][column] + " ");
    }

    System.out.println();
}

58. Iterating Collections#

Arrays have fixed-size language-level structure.

Java also provides the Collections Framework with types such as:

  • List
  • Set
  • Map

We only need enough collection knowledge here to understand iteration.


59. Iterating a List#

Java
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();

        names.add("Amit");
        names.add("Riya");
        names.add("Neha");

        for (String name : names) {
            System.out.println(name);
        }
    }
}

Output:

Output
Amit
Riya
Neha

The enhanced loop works because List types are iterable.


60. Iterating with an Iterator#

A new concept appears here.

An Iterator is an object used to move through elements sequentially.

Typical operations include:

Java
hasNext()

which asks:

Is another element available?

and:

Java
next()

which returns the next element.

Example:

Java
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();

        names.add("Amit");
        names.add("Riya");
        names.add("Neha");

        Iterator<String> iterator = names.iterator();

        while (iterator.hasNext()) {
            String name = iterator.next();
            System.out.println(name);
        }
    }
}

Output:

Output
Amit
Riya
Neha

Conceptually:

Output
List
 ↓
iterator()
 ↓
hasNext()?
 ↓ Yes
next()
 ↓
Process element
 ↓
Repeat

61. Why Would We Use Iterator Directly?#

One important reason is controlled removal during iteration.

Risky:

Java
List<String> names = new ArrayList<>();

names.add("Amit");
names.add("Riya");
names.add("Neha");

for (String name : names) {
    if (name.equals("Riya")) {
        names.remove(name);
    }
}

Structural modification of many ordinary collections while using their fail-fast iteration mechanism can cause ConcurrentModificationException.

A standard iterator-removal approach:

Java
Iterator<String> iterator = names.iterator();

while (iterator.hasNext()) {
    String name = iterator.next();

    if (name.equals("Riya")) {
        iterator.remove();
    }
}

Important precision:

ConcurrentModificationException is a fail-fast behavior used by many standard collection iterators. It should not be treated as a synchronization guarantee, and not every collection has identical iteration behavior.


62. Iterating a Set#

Java
import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Set<String> technologies = new HashSet<>();

        technologies.add("Java");
        technologies.add("Spring");
        technologies.add("Angular");

        for (String technology : technologies) {
            System.out.println(technology);
        }
    }
}

Do not rely on HashSet iteration order unless the chosen collection type/API contract provides the ordering semantics you require.


63. Iterating a Map#

A Map stores key-value mappings.

Example:

Java
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<Integer, String> employees = new HashMap<>();

        employees.put(101, "Amit");
        employees.put(102, "Riya");
        employees.put(103, "Neha");

        for (Map.Entry<Integer, String> entry : employees.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }
    }
}

Using:

Java
entrySet()

is a natural choice when both key and value are needed.

If only keys are required:

Java
for (Integer id : employees.keySet()) {
    System.out.println(id);
}

If only values are required:

Java
for (String name : employees.values()) {
    System.out.println(name);
}

64. Why entrySet() Is Often Preferred for Key + Value#

This:

Java
for (Integer key : map.keySet()) {
    String value = map.get(key);
}

works for many maps.

But if you need both pieces, this expresses intent directly:

Java
for (Map.Entry<Integer, String> entry : map.entrySet()) {
    Integer key = entry.getKey();
    String value = entry.getValue();
}

The exact performance difference depends on the map implementation, but entrySet() also avoids redundant conceptual lookup and clearly communicates "iterate mappings."


65. Traditional Loop vs Enhanced Loop vs Iterator#

RequirementPreferred starting point
Need numeric indexTraditional for
Reverse traversalTraditional for
Custom steppingTraditional for
Only process every elementEnhanced for
Need iterator-specific removalIterator
Condition-driven external statewhile
Execute before first condition testdo-while

Don't select syntax based only on what is shortest.

Select the structure that best communicates the intended control flow.


66. Common Loop Mistakes#

Loops are simple syntactically, but they produce many real bugs because a small mistake can repeat thousands or millions of times.

We will examine the important ones carefully.


Mistake 1 — Wrong Boundary#

Risky#

Java
int[] values = {10, 20, 30};

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

Why developers make it#

They think:

"I need to reach the length."

But array indexes stop at:

Output
length - 1

Consequence#

ArrayIndexOutOfBoundsException.

Preferred#

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

Debugging clue#

Look at:

  • initial index
  • comparison operator
  • final valid index

Interview connection#

Classic off-by-one question.


67. Mistake 2 — Missing Update#

Buggy#

Java
int i = 1;

while (i <= 5) {
    System.out.println(i);
}

Why risky#

i remains 1.

Consequence#

Infinite execution until externally stopped or the environment fails/intervenes.

Correct#

Java
int i = 1;

while (i <= 5) {
    System.out.println(i);
    i++;
}

68. Mistake 3 — Updating in the Wrong Direction#

Buggy#

Java
for (int i = 1; i <= 5; i--) {
    System.out.println(i);
}

i begins at 1.

Condition:

Java
i <= 5

is true.

Then:

Java
i--

makes values:

Output
0
-1
-2
...

Those values remain <= 5.

The intended termination boundary is never approached.

Correct:

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

69. Mistake 4 — Accidental Semicolon After Loop Header#

Look at:

Java
for (int i = 0; i < 3; i++); {
    System.out.println("Hello");
}

The semicolon immediately after for (...) is an empty loop body.

The following block is separate.

Therefore "Hello" prints only once after the loop finishes.

Indented deceptively:

Java
for (int i = 0; i < 3; i++);
{
    System.out.println("Hello");
}

Preferred:

Java
for (int i = 0; i < 3; i++) {
    System.out.println("Hello");
}

70. Mistake 5 — do-while Semicolon Confusion#

Unlike ordinary while syntax:

Java
while (condition) {
}

a do-while requires:

Java
do {
} while (condition);

The final semicolon is part of the syntax.

So don't mechanically apply the "semicolon after loop is always wrong" rule.

Context matters.


71. Mistake 6 — Modifying the Enhanced-For Primitive Variable#

Risky assumption:

Java
int[] numbers = {1, 2, 3};

for (int number : numbers) {
    number *= 2;
}

Some learners expect the array to become:

Output
2, 4, 6

It does not.

Use indexes when replacing array values:

Java
for (int i = 0; i < numbers.length; i++) {
    numbers[i] *= 2;
}

72. Mistake 7 — Structural Modification During Collection Iteration#

Risky:

Java
for (String item : items) {
    if (item.isEmpty()) {
        items.remove(item);
    }
}

For many ordinary collections, this can interfere with fail-fast iteration.

Possible better approaches include:

Java
Iterator<String> iterator = items.iterator();

while (iterator.hasNext()) {
    if (iterator.next().isEmpty()) {
        iterator.remove();
    }
}

or an appropriate collection API such as:

Java
items.removeIf(String::isEmpty);

removeIf was added in Java 8 via the Collection API.

Don't use an alternative API merely because it is shorter; choose based on the actual requirement and mutation semantics.


73. Mistake 8 — Assuming All Collections Support Index-Based Access Efficiently#

This code is natural for ArrayList:

Java
for (int i = 0; i < list.size(); i++) {
    System.out.println(list.get(i));
}

But suppose list is a LinkedList.

Repeated indexed get(i) operations can require traversal through the list, potentially making a seemingly simple loop much more expensive.

For sequential traversal:

Java
for (String value : list) {
    System.out.println(value);
}

is usually a better general expression.

Production lesson:

Understand the data structure you're iterating, not just the loop syntax.

74. Mistake 9 — Expensive Work Repeated in Loop Conditions#

Consider conceptually:

Java
while (calculateExpensiveState()) {
    process();
}

This may be correct if the state genuinely must be recalculated every iteration.

But if the value doesn't need repeated calculation, unnecessary work can become significant.

Never hoist a condition blindly, though.

If its changing value determines loop correctness, evaluating it each iteration is required.

Optimization must preserve semantics.


75. Mistake 10 — Integer Overflow in Loop Control#

Consider:

Java
for (int i = 0; i >= 0; i++) {
}

It may look infinite.

But Java int eventually overflows from:

Output
2147483647

to:

Output
-2147483648

At that point:

Java
i >= 0

becomes false.

This would take a large number of iterations, but the conceptual lesson matters:

Primitive numeric types have finite ranges.

Another dangerous boundary pattern:

Java
for (int i = start; i <= Integer.MAX_VALUE; i++) {
}

When i reaches Integer.MAX_VALUE, incrementing overflows to Integer.MIN_VALUE.

Depending on the condition, behavior may surprise you.


76. Mistake 11 — Floating-Point Loop Counters#

Consider:

Java
for (double value = 0.0; value != 1.0; value += 0.1) {
    System.out.println(value);
}

Binary floating-point representation means decimal values such as 0.1 are not always represented exactly.

Therefore equality-based termination can be unreliable.

For fixed iteration counts, prefer an integer counter:

Java
for (int i = 0; i <= 10; i++) {
    double value = i / 10.0;
    System.out.println(value);
}

General production rule:

Avoid depending on exact floating-point equality for loop termination unless you fully understand the representation and requirement.

77. Mistake 12 — Wrong Nested-Loop Variable#

Bug:

Java
for (int i = 0; i < 3; i++) {
    for (int j = 0; i < 3; j++) {
        System.out.println(i + "," + j);
    }
}

Look carefully.

Inner condition:

Java
i < 3

instead of:

Java
j < 3

Since i doesn't change inside the inner loop, the inner loop may become effectively infinite until some other failure such as integer overflow behavior influences it.

Correct:

Java
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        System.out.println(i + "," + j);
    }
}

This is why i/j mistakes are common in nested logic.


78. Mistake 13 — Misunderstanding break Scope#

Java
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (j == 1) {
            break;
        }
    }
}

A plain break exits the inner loop.

It does not automatically terminate every surrounding loop.

Use a label or restructure the logic if outer termination is required.


79. Mistake 14 — Misunderstanding continue#

Incorrect mental model:

Output
continue = stop loop

Correct:

Output
continue = stop current iteration's remaining work
           and proceed according to loop continuation rules

For a for loop, the update expression is still involved when continuing to the next iteration.

For while, you must ensure required state changes haven't been accidentally skipped.


80. Mistake 15 — Deep Nesting#

Technically valid:

Java
for (...) {
    if (...) {
        for (...) {
            if (...) {
                for (...) {
                    // ...
                }
            }
        }
    }
}

The problem is not compilation.

It is maintainability.

Deep control flow can make it difficult to understand:

  • which condition applies
  • what break exits
  • what continue skips
  • where state changes
  • why execution terminates

Possible improvements:

  • guard clauses
  • helper methods
  • better data structures
  • algorithm redesign
  • early exits

The best solution depends on the requirement.


81. Edge Cases and Traps#

Empty array#

Java
int[] values = {};

for (int value : values) {
    System.out.println(value);
}

The body executes zero times.

Perfectly valid.

But this is not valid:

Java
int minimum = values[0];

because there is no first element.


82. Null Array#

Java
int[] values = null;

for (int value : values) {
    System.out.println(value);
}

This throws:

Output
NullPointerException

because there is no array object to iterate.

Production code should define whether null is:

  • impossible by contract
  • invalid input
  • equivalent to empty
  • something that must be rejected

Do not randomly add null checks without understanding the API contract.


83. Empty Collection#

Java
List<String> names = new ArrayList<>();

for (String name : names) {
    System.out.println(name);
}

No iterations occur.

This is normal.


84. Loop over Mutable State#

Consider:

Java
int limit = 5;

for (int i = 0; i < limit; i++) {
    limit--;
}

Both i and limit change.

Tracing this mentally becomes harder.

The loop may terminate earlier than expected.

Whenever the boundary itself changes inside a loop, ask:

Is that behavior intentional?

85. Loop Condition with Side Effects#

Possible:

Java
while (index++ < 5) {
    // ...
}

But mixing state modification into complex conditions can reduce readability and increase off-by-one risk.

Often clearer:

Java
while (index < 5) {
    index++;
}

This is not a universal ban on side effects in expressions. The point is to prefer control flow that other developers can reason about reliably.


86. Internal Working: What the JVM Actually Sees#

At source-code level, Java offers:

Java
for
while
do-while
enhanced for

But compiled bytecode ultimately uses conditional and unconditional branch instructions to control execution.

Conceptually:

Output
Condition check
   ↓
Conditional jump
   ↓
Body
   ↓
Jump back

The Java compiler converts high-level loop syntax into lower-level control flow.

Later, the JVM's runtime execution engine and JIT compiler may optimize hot code.

This is why two different loop syntaxes can produce similar low-level behavior.

You should choose high-level syntax mainly for:

  • correctness
  • intent
  • maintainability
  • appropriate access pattern

rather than assuming one syntax is always fundamentally faster.


87. Enhanced for Translation Concept#

For an array, the language's model is conceptually similar to maintaining:

Output
array reference
index
array length

For an Iterable, it is conceptually similar to:

Java
Iterator<Type> iterator = collection.iterator();

while (iterator.hasNext()) {
    Type value = iterator.next();
}

This matters because it explains:

  • why enhanced-for supports arrays
  • why it supports Iterable
  • why index is not exposed
  • why collection iterator behavior affects enhanced-for iteration

88. Production Performance Perspective#

Loops themselves are extremely common and not inherently problematic.

Performance problems usually come from what happens inside them or from the number of iterations.

Suppose:

Java
for (Customer customer : customers) {
    loadOrdersFromDatabase(customer);
}

If there are 10,000 customers and every iteration performs a separate database query, the real performance problem may be the repeated I/O.

The loop is simply exposing a broader design issue.

Potential concerns:

Output
Loop
 ↓
How many iterations?
 ↓
What work per iteration?
 ↓
CPU?
Memory allocation?
Database call?
Network call?
Disk I/O?
Lock?
Nested scan?

Always analyze total work.


89. Avoid Premature Micro-Optimization#

Do not automatically rewrite:

Java
for (String item : items)

into some obscure loop because you heard that one form might theoretically be faster.

Modern JVMs perform sophisticated runtime optimizations.

Choose the clear correct algorithm first.

Optimize when:

  • profiling identifies a bottleneck
  • the complexity is obviously problematic
  • data-volume characteristics justify it
  • latency/throughput requirements demand it

90. Nested Loops and Algorithmic Cost#

Suppose:

Java
for (Customer customer : customers) {
    for (Order order : orders) {
        if (order.getCustomerId() == customer.getId()) {
            // ...
        }
    }
}

If there are:

Output
100,000 customers
100,000 orders

comparing every order against every customer can be extremely expensive.

A better data structure, lookup table, query strategy, or algorithm may reduce the work.

Production lesson:

Often the best loop optimization is not a different loop syntax. It is a better algorithm or data structure.

91. Readability and Maintainability#

Compare:

Java
for (int i = 0; i < employees.size(); i++) {
    System.out.println(employees.get(i).getName());
}

with:

Java
for (Employee employee : employees) {
    System.out.println(employee.getName());
}

If index is irrelevant, the enhanced form better communicates:

Process every employee.

But if the index matters:

Java
for (int i = 0; i < employees.size(); i++) {
    System.out.println((i + 1) + ". " + employees.get(i).getName());
}

the indexed version expresses the requirement naturally.


92. break vs Flag#

Two possible approaches:

Flag#

Java
boolean found = false;

for (int value : values) {
    if (value == target) {
        found = true;
    }
}

Early exit#

Java
boolean found = false;

for (int value : values) {
    if (value == target) {
        found = true;
        break;
    }
}

If we need only existence, early exit avoids unnecessary later comparisons.

But don't force break if all items must be processed for another reason.

The requirement determines the correct pattern.


93. continue vs Nested if#

Approach A:

Java
for (Employee employee : employees) {
    if (employee.isActive()) {
        process(employee);
    }
}

Approach B:

Java
for (Employee employee : employees) {
    if (!employee.isActive()) {
        continue;
    }

    process(employee);
}

Both can be good.

When processing logic becomes large, early continue can reduce nesting.

When the body is tiny, the direct if can be simpler.

This is a readability decision, not a universal correctness rule.


94. Loop Testing Strategy#

Loops need boundary-oriented tests.

Suppose a method processes:

Java
for (int i = 0; i < values.length; i++) {
}

Useful tests include:

  • empty array
  • one element
  • several elements
  • first element matches
  • last element matches
  • no element matches
  • duplicates
  • negative values where relevant
  • minimum/maximum domain values
  • null if contract allows or rejects null

For nested loops:

  • zero rows
  • one row
  • uneven row sizes
  • empty inner row
  • large dimensions

Testing boundaries catches many loop defects.


95. Practical Example — Employee Salary Total#

Requirement:

Calculate the total salary of all active employees.

Learning model:

Java
class Employee {
    String name;
    double salary;
    boolean active;

    Employee(String name, double salary, boolean active) {
        this.name = name;
        this.salary = salary;
        this.active = active;
    }
}

Process:

Java
Employee[] employees = {
    new Employee("Amit", 50000, true),
    new Employee("Riya", 60000, false),
    new Employee("Neha", 55000, true)
};

double total = 0;

for (Employee employee : employees) {
    if (!employee.active) {
        continue;
    }

    total += employee.salary;
}

System.out.println(total);

Output:

Output
105000.0

Concepts combined:

Output
Enhanced for
+
Condition
+
continue
+
Accumulator

This is how real programming knowledge works: concepts combine rather than remaining isolated chapters.


96. Practical Example — Search an Employee#

Java
Employee foundEmployee = null;
String requiredName = "Neha";

for (Employee employee : employees) {
    if (employee.name.equals(requiredName)) {
        foundEmployee = employee;
        break;
    }
}

if (foundEmployee != null) {
    System.out.println("Employee found");
}

Concepts:

  • traversal
  • comparison
  • search pattern
  • break
  • state/result variable

For large searchable datasets, repeated linear searches may not be the best production strategy. A Map, database index, or other lookup structure may be more suitable.

Again:

Loop syntax is only one part of algorithm design.

97. Practical Example — Validate All Values#

Requirement:

Determine whether every score is between 0 and 100.
Java
int[] scores = {80, 90, 75, 110};
boolean valid = true;

for (int score : scores) {
    if (score < 0 || score > 100) {
        valid = false;
        break;
    }
}

System.out.println(valid);

Output:

Output
false

Why break?

The requirement asks:

Are all values valid?

The first invalid value is sufficient to prove the final answer is false.


98. Practical Example — First Duplicate Using Nested Loops#

Learning example:

Java
int[] values = {4, 8, 2, 8, 5};
boolean duplicateFound = false;

outer:
for (int i = 0; i < values.length; i++) {
    for (int j = i + 1; j < values.length; j++) {
        if (values[i] == values[j]) {
            System.out.println("Duplicate: " + values[i]);
            duplicateFound = true;
            break outer;
        }
    }
}

if (!duplicateFound) {
    System.out.println("No duplicates");
}

Output:

Output
Duplicate: 8

This is useful for learning nested loops and labeled break.

However, the nested scan is approximately quadratic for large inputs.

A production solution may use a Set to detect duplicates more efficiently.

Learning example and production design are not always identical.


99. Comparison: Indexed for vs Enhanced for#

DimensionIndexed forEnhanced for
Gives indexYesNo
Reverse traversalEasyNot directly
Custom stepYesNo
Replacing array slotsYesNot through loop variable
Readability for simple traversalGoodUsually excellent
ArraysYesYes
Iterable collectionsVia APIs/index where supportedYes
Iterator semanticsNot necessarilyUsed for Iterable
Best usePosition-sensitive traversalElement-focused traversal

Decision#

Output
Need position/control?
→ indexed for

Need each item only?
→ enhanced for

100. Comparison: break vs continue vs return#

A third statement is often confused with them: return.

Suppose we're inside a method.

Java
void process() {
    for (...) {
        ...
    }
}

continue#

Output
Leave current iteration remainder
→ continue loop

break#

Output
Leave loop
→ continue method after loop

return#

Output
Leave method entirely

Example:

Java
public static void demo() {
    for (int i = 1; i <= 5; i++) {
        if (i == 3) {
            return;
        }

        System.out.println(i);
    }

    System.out.println("After loop");
}

Output:

Output
1
2

After loop never executes because return exits the method.


101. Quick Decision Rules#

Output
Repeat a known number of times?
→ for

Repeat while a condition remains true?
→ while

Must run once before testing?
→ do-while

Process every array/Iterable element?
→ enhanced for

Need array/list index?
→ indexed for

Need to exit loop immediately?
→ break

Need to skip one iteration?
→ continue

Need to exit a particular outer nested loop?
→ labeled break

Need to move directly to next iteration of outer loop?
→ labeled continue

Need iterator-controlled removal?
→ Iterator

102. COMPLETE REVISION#

One-Line Definitions#

Loop: A control structure that repeatedly executes statements according to a continuation rule.

Iteration: One execution cycle of a loop.

Loop control variable: State used to control or track loop progression.

for: Loop suited to explicit initialization, condition, and progression.

while: Loop that repeats while its condition is true.

do-while: Loop that executes its body before checking whether to repeat.

Enhanced for: Element-focused traversal over arrays and Iterable objects.

Nested loop: A loop placed inside another loop.

Infinite loop: A loop with no naturally reached terminating condition.

break: Immediately exits the targeted loop or labeled statement.

continue: Skips the remaining current iteration and proceeds toward another iteration.

Labeled break: Exits a particular labeled enclosing statement.

Labeled continue: Continues a particular labeled enclosing iteration statement.


103. Syntax Revision#

for#

Java
for (initialization; condition; update) {
    // body
}

while#

Java
while (condition) {
    // body
}

do-while#

Java
do {
    // body
} while (condition);

Enhanced for#

Java
for (Type item : source) {
    // body
}

break#

Java
break;

continue#

Java
continue;

Label#

Java
outer:
for (...) {
    ...
}

Labeled break#

Java
break outer;

Labeled continue#

Java
continue outer;

104. If You Remember Only 10 Things#

  1. A loop repeats code according to a control rule.
  2. for is usually clearest for known ranges or progression.
  3. while checks before executing and may run zero times.
  4. do-while executes once before its first condition check.
  5. Enhanced for is ideal when you need elements but not indexes.
  6. Array indexes run from 0 to length - 1.
  7. break terminates the loop; continue skips only the current remainder.
  8. Missing or incorrect state updates commonly create infinite loops.
  9. Nested loops can multiply computational work.
  10. Production performance depends more on algorithm, data structure, and work inside the loop than on superficial loop syntax.

105. Memory Hooks#

Output
FOR
→ "From here to there"

WHILE
→ "As long as this is true"

DO-WHILE
→ "Do it once, then ask"

FOR-EACH
→ "Give me every element"

BREAK
→ "I'm done with this loop"

CONTINUE
→ "Skip this one"

LABEL
→ "Control that specific outer structure"

106. Final Knowledge Map#

Output
Loops and Iteration
│
├── Why Repetition Exists
│   ├── Repeated operations
│   ├── Iteration
│   └── Loop state
│
├── Core Loops
│   ├── for
│   │   ├── initialization
│   │   ├── condition
│   │   ├── update
│   │   ├── forward traversal
│   │   ├── reverse traversal
│   │   ├── custom step
│   │   └── multiple variables
│   │
│   ├── while
│   │   ├── pre-condition
│   │   ├── condition-driven execution
│   │   └── zero-or-more iterations
│   │
│   ├── do-while
│   │   ├── post-condition
│   │   └── one-or-more iterations
│   │
│   └── enhanced for
│       ├── arrays
│       ├── Iterable
│       ├── element traversal
│       └── index limitations
│
├── Complex Iteration
│   ├── nested loops
│   ├── multidimensional arrays
│   └── algorithmic cost
│
├── Loop Control
│   ├── break
│   ├── continue
│   ├── labeled break
│   └── labeled continue
│
├── Loop Patterns
│   ├── counter
│   ├── accumulator
│   ├── search
│   ├── first match
│   ├── min/max
│   ├── filter/skip
│   ├── flag
│   ├── sentinel
│   ├── bounded retry
│   ├── reverse traversal
│   └── two-ended traversal
│
├── Arrays
│   ├── indexes
│   ├── boundaries
│   ├── updates
│   └── multidimensional traversal
│
├── Collections
│   ├── enhanced for
│   ├── Iterator
│   ├── List
│   ├── Set
│   └── Map
│
├── Common Bugs
│   ├── off-by-one
│   ├── missing update
│   ├── wrong update direction
│   ├── accidental semicolon
│   ├── wrong nested variable
│   ├── unsafe structural modification
│   ├── continue/update interaction
│   ├── overflow
│   └── floating-point termination
│
└── Production Thinking
    ├── readability
    ├── algorithm complexity
    ├── collection characteristics
    ├── I/O inside loops
    ├── lifecycle/termination
    ├── mutation safety
    └── boundary testing

Practice lab

Prove what you just learned