Loops
Why Do We Need Loops?
If you want to print "Hello" five times, you could simply write the print command five times. But what if you need to process a database of 10,000 users? Or search through a million pixels in an image to find a specific color? Writing linear code for massive or dynamic datasets is impossible.
We need a way to tell the computer: "Take this small block of instructions and repeat it until a specific condition is met." This is where loops come in. They are the engine of automation, allowing a few lines of code to process millions of data points in milliseconds.
What Is a Loop?
Definition
A loop repeats a block of code until its stopping point is reached: either a condition turns false, or, in a for-each loop, every element has been visited.
In Java that condition must be a Boolean. C, C++, Python and JavaScript apply their own truthiness rules to it, which Conditions covers.
How Loops Work
Almost every loop relies on four fundamental pillars to operate safely:
- Initialization: Setting up a starting variable (the counter or tracker) before the loop begins.
- Condition: The test evaluated before every single cycle. If it holds, the loop runs. If it does not, the loop stops.
- Loop Body: The actual block of code (instructions) being repeated.
- Iteration / Update: The mechanism that modifies the initialization variable (usually adding or subtracting 1) so that the condition will eventually become
false.
Note
A quick note on arrays. Several examples below use an array: a fixed-size, numbered list of values. Three facts are all you need for now. Positions are called indexes, indexes start at 0 rather than 1, and array.length gives the count. An array of 5 items has valid indexes 0, 1, 2, 3 and 4, so the last index is always length - 1, never length. Arrays get a full chapter of their own later.
The while Loop
The while loop is the simplest loop. It evaluates the condition before executing the body.
It is best used when there is no counter driving the loop, and it ends because something in the body changed: reading a file until it runs out, or waiting for a user to enter a valid password.
int count = 1; // 1. Initializationwhile (count <= 3) { // 2. Condition System.out.println("Loop " + count); // 3. Body count++; // 4. Update}| Pass | count before | count <= 3? | Prints | count after |
|---|---|---|---|---|
| 1 | 1 | true | Loop 1 | 2 |
| 2 | 2 | true | Loop 2 | 3 |
| 3 | 3 | true | Loop 3 | 4 |
| 4 | 4 | false | — | — |
Note the fourth pass. The condition is checked one extra time, the time it fails, and that check is what ends the loop. A loop that prints three lines evaluates its condition four times.
The do–while Loop
The do-while loop is an inverted while loop. It executes the body first, and checks the condition after.
This guarantees that the loop body will always run at least once, even if the condition is false from the very beginning. It is frequently used for user menus ("Do this action, while the user hasn't pressed Quit").
// showMenu(), readChoice() and handle() are functions you would write yourselfint choice;do { showMenu(); // drawn before anything is checked choice = readChoice(); handle(choice);} while (choice != QUIT);The menu has to appear once before there is any choice to test, which is the shape do-while exists for.
The for Loop
The for loop consolidates initialization, condition, and update into a single, clean line.
It is best when the loop has a clear starting point, boundary, and update, especially when iterating through a range or a collection. You do not have to know the count in advance: for (int i = 0; i < n; i++) is a for loop whose length is only known when it runs.
// Init ; Condition ; Updatefor (int i = 1; i <= 3; i++) { System.out.println("Loop " + i);}The for-each Loop
When you only need each value and do not need its index, a for-each loop is usually cleaner.
int[] numbers = {10, 20, 30}; for (int number : numbers) { System.out.println(number);}Use a traditional for loop when you need the index. Use a for-each loop when you only need the elements.
Choosing Between for, while, and do–while
- Use
forwhen the loop has a counter or an iteration variable. The header keeps initialization, condition and update in one place, where they are hard to forget. - Use
whilewhen there is no counter, and the loop ends because something in the body changed: a flag flipped, a file ran out, input became valid. - Use
do-whilewhen the body must run once before there is anything to test.
What if the exit point is in the middle of the body? Then neither a counter nor a leading test fits, and the usual answer is while (true) with a break at the point where the work is done. A menu loop is the standard example, and it is how a do-while is written in a language that does not have one.
Loop Boundaries
Managing the start and end of a loop is where most beginners struggle.
Think in ranges. Rather than memorising < against <=, read the header and write down the values the counter actually takes.
for (int i = 0; i < n; i++) -> i = 0, 1, 2, ..., n - 1 (n times)for (int i = 1; i <= n; i++) -> i = 1, 2, 3, ..., n (n times)Both run n times. The bound moved because the starting point moved, which is the actual rule underneath the two symbols.
The same loop written both ways, with n fixed at 5:
for (int i = 0; i < 5; i++) -> 0 -> 1 -> 2 -> 3 -> 4 -> stopfor (int i = 0; i <= 5; i++) -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> stopThe difference between < and <= is only one value, but that one value is responsible for countless off-by-one bugs.
- Inclusive vs Exclusive:
< 10is exclusive (stops at 9).<= 10is inclusive (stops at 10). - Off-by-one errors (OBOB): Since arrays start at index
0, looping to<= array.lengthwill cause an out-of-bounds crash. You must use< array.length. - Backward iteration: To read data in reverse, initialize at the end, set the condition to
>= 0, and decrement (i--):for (int i = array.length - 1; i >= 0; i--)
The fencepost problem. A related bug that is not quite an off-by-one. Joining five values with a comma needs five values and only four separators, so a loop that writes a separator on every pass leaves one dangling at the end:
1, 2, 3, 4, 5, <- a separator after every item1, 2, 3, 4, 5 <- what you wantedThe usual fixes are to write the separator before every item except the first, or to write the first item outside the loop. Fence posts and fence panels: five posts hold four panels.
Loop Control Statements
break and continue get a full treatment in Control Flow, which comes next. Here is what you need in order to read the loops in this chapter:
break leaves the loop entirely:
for (int i = 1; i <= 10; i++) { if (i == 5) break; System.out.println(i);}1234continue skips the rest of the current pass and goes on to the next one:
for (int i = 1; i <= 5; i++) { if (i == 3) continue; System.out.println(i);}1245break ends the loop. continue ends only the current iteration.
In a C-style for loop, continue skips the rest of the body and then executes the loop's update expression before checking the condition again. In a Python for loop, continue simply moves on to the next item, because there is no update expression to skip. A Python while loop has the same hazard as Java's, since there the update is just a statement in the body.
Nested Loops
A loop placed inside another loop is a nested loop.
Think of a digital clock: the minute hand (outer loop) ticks once, and the second hand (inner loop) must tick 60 times before the minute hand ticks again. For every single iteration of the outer loop, the inner loop must complete its entire cycle.
for (int out = 1; out <= 3; out++) { for (int in = 1; in <= 2; in++) { System.out.println("Out: " + out + ", In: " + in); }}// Runs 3 * 2 = 6 total times.Out: 1, In: 1Out: 1, In: 2Out: 2, In: 1Out: 2, In: 2Out: 3, In: 1Out: 3, In: 2Read the left column: it changes slowly. The right column resets to 1 every time the outer counter moves. The inner loop does not continue from where it left off, it starts over completely, and that restart is why the counts multiply instead of add.
Loop Conditions and Boolean Logic
Loop conditions are not restricted to simple comparisons. You can use logical operators (&&, ||) to create multi-faceted stopping points.
The flag pattern. A boolean that records whether something happened, so the loop can stop early and the code after it can tell what occurred:
boolean targetFound = false;int index = 0; while (index < array.length && !targetFound) { if (array[index] == target) { targetFound = true; } index++;}The order of the two conditions matters, for the same reason it did in Conditions: index < array.length must be checked first, because once it fails there is no valid element to read. && never evaluates its right side after the left side fails.
Compare that with break: the same search written as a for loop with if (...) break; needs no flag at all. The flag earns its place when the code after the loop needs to know whether the search succeeded.
Counters, Accumulators and Traversal
Loops are frequently used to tally data.
- Counter: Tracks how many times something happens (
count++). - Accumulator: Keeps a running total of values (
sum += value).
int sum = 0;for (int i = 1; i <= 5; i++) { sum += i; // Accumulating 1 + 2 + 3 + 4 + 5}Loops are also the primary tool for reading data structures from start to finish.
- Arrays: Use a
forloop utilizing the index, usually from0tolength - 1. - Strings: Strings behave like sequences of characters and are traversed the same way, whether you are checking for vowels, palindromes, or substrings. In C, and in C++ when you use
char[], a string is literally an array of characters; Java wraps one in aStringobject and Python has no character type at all. - Collections: Most modern languages offer a "for-each" loop to cleanly traverse lists and sets without managing an index variable:
for (String name : nameList).
Infinite Loops
An infinite loop occurs when the loop's condition never evaluates to false.
- How they happen: Forgetting the update statement (
i++), creating a logically impossible condition (while (i > 0)wheniis constantly increasing), or misusingcontinuein awhileloop. - How to prevent them: Always double-check that your update statement moves the initialization variable closer to the termination condition.
The simplest one:
int i = 0; while (i < 5) { System.out.println(i);}What is missing? i never changes, so i < 5 stays true forever and the loop prints 0 until you kill it. One line fixes it:
while (i < 5) { System.out.println(i); i++;}The continue case is the least obvious of the three and the most worth seeing:
int i = 0;while (i < 10) { if (i == 5) continue; // skips i++, so i stays 5 forever System.out.println(i); i++;}continue jumps straight to the condition test, skipping everything below it, including the update. In a for loop this is safe, because the update lives in the loop header and always runs. In a while loop the update is just another statement in the body, and continue skips it. This is the strongest practical argument for preferring for when you have a counter.
Loop Invariants: Your First Look
You do not need to master loop invariants yet. The important idea is that we can keep track of something that stays true throughout the loop. Later, this becomes a powerful tool for proving algorithms correct.
A loop invariant is a property that is true before the loop starts, stays true through every iteration, and is therefore still true after the loop finishes.
The simplest possible one:
int sum = 0;for (int i = 0; i < n; i++) { sum += arr[i];}The invariant is: after k iterations, sum holds the total of the first k elements.
It has three parts, and they have names you will meet again:
- Initialization: it is true at the start, when
kis zero andsumis zero. - Maintenance: each iteration adds exactly the next element, so if it was true before the pass it is true after it.
- Termination: when the loop ends
kisn, which is the same as sayingsumholds the total of the whole array: the thing you wanted, proved rather than assumed.
That is the whole technique, and it is how sorting and binary search are shown to be correct rather than merely tested.
Time Complexity of Loops
Before you can reason about cost, you have to know how many times a loop runs.
for (int i = 0; i < n; i++)runs exactlyntimes.for (int i = 0; i < n; i += 2)runs aboutn/2times, exactly⌈n/2⌉, since the last step may land short of the bound.
In Data Structures and Algorithms, we evaluate code performance using Big-O notation, which directly measures loop behavior as the input size (n) grows.
What follows is the pattern-recognition half of it: enough to look at a loop and name its shape. The formal treatment - why the smaller terms are dropped, how sequential loops differ from nested ones, what the classes cost at a million elements - is Big O and Time Complexity, which come later in Foundations.
- Constant Loops
O(1):for (int i = 0; i < 10; i++)(Always runs 10 times, regardless ofn). - Linear Loops
O(n):for (int i = 0; i < n; i++)(Runs directly in proportion ton). - Nested Loops
O(n²): AnO(n)loop inside anO(n)loop. Ifn = 10, it runs 100 times. The cost grows fast: doublingnquadruples the work. - Dependent Loops
O(n²):for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) }. The inner loop shrinks as the outer loop grows, forming a triangle pattern. The passes add up ton + (n-1) + (n-2) + ... + 1, which isn(n+1)/2, and that is stillO(n²). - Logarithmic Loops
O(log n):for (int i = 1; i < n; i *= 2). The loop variable doubles every iteration. Doubling reachesnin about log₂ n steps, so a million elements take roughly twenty passes.
Loops in DSA and Problem Solving
Loops are the operational chassis for almost every algorithm. A handful of shapes account for most of them:
Traversal visit every elementSearching stop when the target is foundAccumulation build a single result from many valuesFrequency counting tally how often each value appearsNested traversal compare or combine every pairTwo pointers move two indices based on conditionsSliding window maintain a moving rangeThe algorithms themselves come later. What matters now is that each one is a loop with a particular update rule.
Binary Search uses a while loop that halves the search space every iteration. The Sliding Window technique uses a for loop to drag a frame across an array. Two Pointers use a while loop (left < right) to converge on a solution from opposite ends of a dataset.
Loops Across Languages
While the logic remains the same, syntax varies:
- Java / C++: Use the standard three-part
forloop (for (int i=0; i<10; i++)). - Python: Does not use the three-part C-style loop. It iterates over ranges or collections:
for i in range(10):orwhile count < 5:. - JavaScript: Supports traditional
forloops, but heavily relies on array methods like.forEach()or thefor...ofsyntax to read data directly. do-while: Java, C++ and JavaScript have it. Python does not; the idiom there iswhile True:with abreakat the bottom.
Common Mistakes and Edge Cases
Watch out
-
Scoping: In Java, C++, and JavaScript with
let, a variable declared inside the loop body is scoped to that block and cannot be accessed outside it. Python and JavaScript's oldervarbehave differently: the variable outlives the loop, and so does the loop counter itself. If you need a value after the loop ends in a block-scoped language, declare it before the loop. -
Modifying a collection while looping: Modifying a collection while iterating over it can cause skipped elements, invalid iteration, or runtime errors, depending on the language and the collection. Use the collection's supported removal mechanism, or build a separate result.
-
Semicolon after a loop. The stray
;becomes the loop's entire body, so the loop runs all ten iterations doing nothing at all, and the line below it executes once, disconnected from the loop:
int sum = 0;int i; for (i = 0; i < 10; i++); // the ; IS the body: ten empty passes sum += i; System.out.println(sum);This compiles, runs, and prints 10. The loop makes ten empty passes, and then sum += i executes exactly once, after the loop has finished, with i already at 10. Nothing warns you, because nothing is wrong with it as far as the compiler is concerned.
Quick Check
- Which loop evaluates its condition after the body executes?
- Why does
for (int i = 0; i <= array.length; i++)cause a crash? - If an outer loop runs 5 times, and its inner loop runs 4 times, how many total executions occur in the inner body?
- What happens if a
whileloop's update step is accidentally removed? - Which time complexity represents a loop where the index doubles (
i *= 2) every iteration?
6. What does this print?
for (int i = 0; i < 5; i++) { System.out.print(i + " ");}7. What does this print?
int x = 1; while (x < 10) { System.out.print(x + " "); x *= 2;}8. What does this print?
for (int i = 1; i <= 5; i++) { if (i == 3) continue; System.out.print(i + " ");}9. How many lines does this print, and what is the last one?
for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 2; j++) { System.out.println(i + "," + j); }}10. What does this print?
for (int i = 1; i <= 3; i++) { System.out.print(i + ", ");}Show answerHide answer
- The
do-whileloop. It runs its body once before testing anything, so the body always executes at least once even when the condition is false from the start. - Because
<=makes the last pass use the indexarray.length, and valid indexes stop one below that. Reading past the end throws an out-of-bounds exception. Use<. - Twenty. The inner loop runs in full on every pass of the outer one, so it is 5 × 4, not 5 + 4.
- The condition never changes, so it never becomes false and the loop runs forever. A
forloop makes the update easier to see, because initialization, condition and update sit together in the header, but it does not guarantee termination:for (int i = 0; i < 5;)loops forever too. O(log n). Doubling reachesnin about log₂ n steps, so a million elements take roughly twenty passes rather than a million.0 1 2 3 4. The counter starts at 0 and the bound is exclusive, so it stops one short of 5.1 2 4 8.xdoubles rather than increments, so it reaches 16 on the next pass and 16 is not less than 10. Four passes, not nine.1 2 4 5.continueskips only the printing fori == 3; the loop itself carries on.- Six lines, and the last is
3,2. The inner loop runs in full for every pass of the outer one. 1, 2, 3,— with a trailing comma and space. Three items need only two separators, but the loop writes one on every pass, so the last one dangles. This is the fencepost problem.
Quick Recap
- Loops automate repetitive work, running until a stopping point is reached.
- Every safe loop requires initialization, a condition, an update, and a body.
- Use
forwhen the loop has a counter,whilewhen it ends because something in the body changed, anddo-whilewhen the body must run once first. - A for-each loop visits every element without an index: use it when you do not need the position.
breakends the loop;continueends only the current pass.- Boundaries are about ranges, not symbols: work out which values the counter actually takes.
- Fencepost:
nitems needn - 1separators. - Nested loops multiply the total number of iterations.
- Counters track occurrences; accumulators track running totals.
- An infinite loop is a condition that never turns false, usually a missing or misdirected update.
- Understanding how a loop scales as data grows (
O(n),O(n²),O(log n)) is the foundation of algorithm analysis. - A loop invariant holds before, during and after the loop, and it is how a loop is shown to be correct rather than merely tested.
Where This Leads
Operators ↓Conditions ↓Loops ↓Control Flow ↓FunctionsAt this point, you can calculate data, make complex decisions, and repeat those actions millions of times. But a loop that always runs to completion is wasteful: once you have found what you were searching for, you want out.
That is what Control Flow Statements are for: break, continue and return, the three ways to override a loop mid-flight. After that come Functions, which wrap all of this into something reusable.
Key takeaway
Loops grant your code the power of automation and scale. By mastering loop boundaries, nested iterations, and termination conditions, you transition from writing programs that process a single data point to writing algorithms that can process the world's information.