Nested Iteration
Why this matters
Imagine you're on the yearbook committee, and your job is to create the big grid of student portraits. You don't just place photos randomly, right? You work systematically. You start with the first row, and you place every student's photo for that row, from left to right. Only when that row is completely full do you move down to the second row and repeat the process. Then the third, and so on, until the page is complete.
That "for each row, handle every column" process is exactly what nested iteration is in programming. It’s a powerful tool for working with grids, tables, pairs of items, and any data that has a two-dimensional structure. In this lesson, we’ll break down how to build and understand these "loops within loops" so you can tackle complex problems with a clear, systematic approach.
Concept overview
flowchart TD
A[Start] --> B{Outer Loop Condition Met?};
B -- No --> I[End];
B -- Yes --> C{Inner Loop Condition Met?};
C -- No --> G[Update Outer Loop Variable];
G --> B;
C -- Yes --> D[Execute Inner Loop Body];
D --> E[Update Inner Loop Variable];
E --> C;
Core explanation
Hello everyone, it's Saavi. Today we're diving into a concept that feels a little like a Russian nesting doll: nested iteration. It’s a fundamental skill, especially for handling anything that looks like a grid or requires comparing items within a set.
What is a Nested Loop?
At its core, a nested loop is simply a loop that lives inside another loop.
// The "outer" loop
for (int i = 0; i < 3; i++) {
// The "inner" loop
for (int j = 0; j < 5; j++) {
// This code runs every time the inner loop iterates
System.out.print("*");
}
// This code runs only when the inner loop finishes
System.out.println();
}
The loop with the variable i is the outer loop. The loop with j is the inner loop.
The Golden Rule of Nested Loops
Here is the single most important rule to remember: For each one iteration of the outer loop, the inner loop runs to completion.
Think of a digital clock.
- The outer loop is the hour.
- The inner loop is the minute.
The hour doesn't tick forward to 3:00 until the minutes have gone all the way from 2:00, 2:01, 2:02... all the way to 2:59. The "minute loop" has to complete its entire 60-step cycle before the "hour loop" takes a single step forward.
Nested loops in Java work the exact same way. The outer loop starts, and then it pauses and hands control over to the inner loop. The inner loop runs and runs and runs until its condition is false. Only then does control return to the outer loop, which completes its first iteration and starts its second. Then the whole process repeats.
Tracing a Nested Loop
Let's trace the code from above to see this in action. The outer loop runs when i is 0, 1, and 2. The inner loop runs when j is 0, 1, 2, 3, and 4.
1. Outer loop starts. i is 0.
- The program enters the outer loop's body.
- It immediately encounters the inner loop.
- Inner loop starts.
jis 0. Prints*.jis 1. Prints*.jis 2. Prints*.jis 3. Prints*.jis 4. Prints*.jbecomes 5. The inner loop conditionj < 5is now false.
- Inner loop ends.
- The program continues in the outer loop's body. It executes
System.out.println(), moving the cursor to a new line. - The outer loop's first iteration is now complete.
Output so far:
*****
2. Outer loop continues. i is 1.
- The program enters the outer loop's body again.
- It encounters the inner loop.
- Inner loop starts again from scratch.
jis 0. Prints*.jis 1. Prints*.- ...and so on until
jis 4.
- Inner loop ends.
- The
System.out.println()runs again.
Output so far:
*****
*****
3. Outer loop continues. i is 2.
- The process repeats one last time. The inner loop runs completely, printing 5 more asterisks. The
printlnmoves to the next line.
Final Output:
*****
*****
*****
The inner loop's body ran a total of 3 * 5 = 15 times. The outer loop's body ran 3 times.
Where Students Get Stuck
Remember the clock. The hour hand doesn't move every time the minute hand moves. It waits. The outer loop is patient. It waits for the inner loop to do all of its work before it continues.
Nested loops are your go-to tool for processing 2D data structures. Think of the outer loop as controlling the rows and the inner loop as controlling the columns.
for (int row = 0; ...)for (int col = 0; ...)
This pattern is so common that you'll see it again when we get to 2D arrays in a later unit. Mastering the flow now will make your life so much easier down the road.
See it in action
Worked examples
Let's walk through a couple of examples to make this concrete.
Printing a Numbered Triangle
Problem: Write code that produces the following output.
1
12
123
1234
Solution Walkthrough:
- 1Analyze the StructureWe see multiple lines, so we know we need a
System.out.println()to create the new lines. This suggests an outer loop that handles each row. There are 4 rows. - 2Outer LoopLet's set up an outer loop that runs 4 times. We'll use a variable
rowthat goes from 1 to 4.for (int row = 1; row <= 4; row++) { // What happens in each row? // ... System.out.println(); // Move to next line after the row is done } - 3Analyze the Inner Pattern
- In row 1, we print up to 1.
- In row 2, we print up to 2.
- In row 3, we print up to 3.
- In row 4, we print up to 4.
It looks like for each
row, we need an inner loop that prints numbers from 1 up to the currentrownumber. The inner loop's stopping point depends on the outer loop's current value. - 4Inner LoopLet's create an inner loop using a variable
col. It should start at 1 and go up to the current value ofrow.for (int col = 1; col <= row; col++) { System.out.print(col); } - 5Combine and FinalizeNow, we place the inner loop inside the outer loop.
```java
public class Triangle {
public static void main(String[] args) {
for (int row = 1; row <= 4; row++) {
for (int col = 1; col <= row; col++) {
System.out.print(col);
}
System.out.println(); // Essential for creating the rows!
}
}
}
```
Finding Duplicate Names in a Roster
Problem: Given an array of names, find and print any names that appear more than once. For a list like {"Maya", "Liam", "Sofia", "Maya", "Carlos"}, the program should identify "Maya".
Solution Walkthrough:
- 1The Core TaskHow do you find a duplicate? You have to compare every name on the list to every other name on the list.
- 2The StrategyThis "every item vs. every other item" is a perfect use case for nested loops.
- The outer loop will pick a name. Let's say it picks "Maya" at index 0.
- The inner loop will then compare that chosen name to all the names that come after it in the list.
- 3Setting up the LoopsLet's say our array is
String[] names.String[] names = {"Maya", "Liam", "Sofia", "Maya", "Carlos"}; // Outer loop picks the first name to compare for (int i = 0; i < names.length; i++) { // Inner loop picks the second name to compare for (int j = i + 1; j < names.length; j++) { // Compare names[i] and names[j] } } - 4
Why
j = i + 1? This is the most critical part of this example.- We don't need to compare a name to itself (
ishould not equalj). - If we've already compared
names[0]andnames[2], we don't need to later comparenames[2]andnames[0]. It's the same comparison. - By starting
jati + 1, we ensure we only compare each pair once and we never compare an element to itself.
- We don't need to compare a name to itself (
- 5Adding the ComparisonInside the inner loop, we use
.equals()to compare the strings.if (names[i].equals(names[j])) { System.out.println("Found a duplicate: " + names[i]); } - 6Full Code
public class FindDuplicates { public static void main(String[] args) { String[] names = {"Maya", "Liam", "Sofia", "Maya", "Carlos"}; for (int i = 0; i < names.length; i++) { for (int j = i + 1; j < names.length; j++) { if (names[i].equals(names[j])) { System.out.println("Found a duplicate: " + names[i]); } } } } }When
iis 0 (names[i]is "Maya"),jwill start at 1. The inner loop will compare "Maya" to "Liam", then "Sofia", then "Maya" (at index 3). It finds a match and prints.
Try it yourself
Ready to try on your own? Don't worry about getting it perfect on the first try. The goal is to think through the logic.
Problem 1: The Other Triangle
Write a program that uses nested loops to print the following pattern:
****
***
**
*
Problem 2: The Team-Up
You have an array of basketball players: String[] players = {"Jordan", "Priya", "Marcus", "Aaliyah"};. Write a program to print out every possible pair of two different players that can be formed from this list. The order doesn't matter (i.e., "Jordan and Priya" is the same as "Priya and Jordan").
Practice — 8 questions
In simple terms, nested iteration is about putting one loop inside of another. The inner loop runs completely, over and over again, once for each single step of the outer loop.
// The "outer" loop
for (int i = 0; i < 3; i++) {
// The "inner" loop
for (int j = 0; j < 5; j++) {
// This code runs every time the inner loop iterates
System.out.print("*");
}
// This code runs only when the inner loop finishes
System.out.println();
}
- 2.11.A: Develop code to represent nested iterative processes and determine the result of these processes.
- 2.11.A.1
- Nested iteration statements are iteration statements that appear in the body of another iteration statement. When a loop is nested inside another loop, the inner loop must complete all its iterations before the outer loop can continue to its next iteration.
flowchart TD
A[Start] --> B{Outer Loop Condition Met?};
B -- No --> I[End];
B -- Yes --> C{Inner Loop Condition Met?};
C -- No --> G[Update Outer Loop Variable];
G --> B;
C -- Yes --> D[Execute Inner Loop Body];
D --> E[Update Inner Loop Variable];
E --> C;
Read what Saavi narrates
Hi everyone, it's Saavi from Shrutam. Let's talk about a programming concept that’s like those little Russian nesting dolls… loops inside of loops.
Imagine you're on the yearbook committee, and you have to lay out all the student portraits in a big grid. You don't do it randomly. You start with the first row, and you place every single photo for that row, from left to right. Only when that row is completely full do you move down to the second row and do it all over again.
That process… for each row, handle every column… is exactly what we call nested iteration. It’s just a loop inside another loop. The most important thing to remember is that the inner loop has to finish all of its work before the outer loop can take its next step.
Let's imagine a simple example. Suppose we want to print a 3 by 5 rectangle of asterisks. We can use an outer loop to handle the three rows, and an inner loop to print the five asterisks for each row.
So, the outer loop starts its first step... let's say for row one. It then tells the inner loop, "Okay, your turn." The inner loop then runs five times, printing an asterisk each time. Star, star, star, star, star. Once the inner loop is done, it hands control back to the outer loop. The outer loop then says, "Great, let's move to a new line," and starts its second step, for row two. Then the whole process repeats. The inner loop prints five more stars.
The final result is a perfect 3 by 5 rectangle.
A really common mistake here is thinking the loops take turns. They don't. The outer loop is patient. It's like the hour hand on a clock. It waits for the minute hand, the inner loop, to complete its entire cycle before it moves.
Once you get that rhythm down, you'll find nested loops are an incredibly powerful tool for solving all sorts of problems. You've got this.
The rule is that the inner loop must run to completion for *every single* iteration of the outer loop.
Visualize a clock. The hour hand (outer loop) only moves after the minute hand (inner loop) has completed its full 60-minute cycle.
This can lead to infinite loops or incorrect behavior because you're modifying the wrong counter. The inner loop needs its own independent counter.
Always use `i` for the first-level loop, `j` for the second, `k` for the third, and so on. Stick to this convention to keep your variables straight.
`System.out.print()` inside the inner loop builds a single line. `System.out.println()` placed *between* the inner and outer loops ends that line and starts a new one for the next outer loop iteration. Putting `println()` inside the inner loop will print every single character on a new line.
Ask yourself: "Do I need a new line after every *character* or after every *row*?" If it's after every row, the `println()` goes in the outer loop, after the inner loop is finished.
This causes an element to be compared with itself (when `i == j`) and causes every pair to be compared twice (e.g., `names[1]` vs `names[3]` and later `names[3]` vs `names[1]`).
When finding unique pairs, start the inner loop's counter at one greater than the outer loop's counter: `for (int j = i + 1; ...)`.
Using `<` vs. `<=` incorrectly will either cut your loop short by one iteration or cause an `ArrayIndexOutOfBoundsException` if you go one step too far.
Trace the first and last iterations by hand. If a loop should run 5 times from 0, the condition is `i < 5` (for `i` = 0, 1, 2, 3, 4). If it's from 1, the condition is `i <= 5` (for `i` = 1, 2, 3, 4, 5).